forked from xuos/xiuos
1、support SDIO driver and mount FAT-FS; 2、support SPI driver; 3、support SPI-LoRa driver; 4、fix heap memory error : start from _bss_end and conflict with stack segment
it is OK
This commit is contained in:
@@ -48,7 +48,7 @@ Modification:
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
;</h>
|
||||
*/
|
||||
.equ Stack_Size, 0x00002000
|
||||
.equ Stack_Size, 0x00004000
|
||||
|
||||
.section .stack
|
||||
.align 3
|
||||
@@ -60,26 +60,6 @@ __StackLimit:
|
||||
__StackTop:
|
||||
.size __StackTop, . - __StackTop
|
||||
|
||||
|
||||
/*
|
||||
;<h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
;</h>
|
||||
*/
|
||||
.equ Heap_Size, 0x00002000
|
||||
|
||||
.if Heap_Size != 0 /* Heap is provided */
|
||||
.section .heap
|
||||
.align 3
|
||||
.globl __HeapBase
|
||||
.globl __HeapLimit
|
||||
__HeapBase:
|
||||
.space Heap_Size
|
||||
.size __HeapBase, . - __HeapBase
|
||||
__HeapLimit:
|
||||
.size __HeapLimit, . - __HeapLimit
|
||||
.endif
|
||||
|
||||
/*
|
||||
;<h> Reset handler start.
|
||||
*/
|
||||
|
||||
@@ -35,9 +35,11 @@ menu "aiit-arm32-board feature"
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool "mount cd card"
|
||||
bool
|
||||
default n
|
||||
config MOUNT_USB
|
||||
bool
|
||||
default n
|
||||
select BSP_USING_SDIO
|
||||
endmenu
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
@@ -51,6 +51,7 @@ extern int HwSramInit(void);
|
||||
extern int Stm32HwAdcInit(void);
|
||||
extern int Stm32HwDacInit(void);
|
||||
extern int Stm32HwLcdInit(void);
|
||||
extern int Stm32HwUsbInit(void);
|
||||
|
||||
static void ClockConfiguration()
|
||||
{
|
||||
@@ -147,6 +148,11 @@ struct InitSequenceDesc _board_init[] =
|
||||
#ifdef BSP_USING_SDIO
|
||||
{"hw sdcard init",HwSdioInit},
|
||||
#endif
|
||||
#ifdef BSP_USING_USB
|
||||
#ifdef BSP_USING_STM32_USBH
|
||||
{ "hw usb", Stm32HwUsbInit },
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BSP_USING_EXTMEM
|
||||
{ "hw extern sram", HwSramInit },
|
||||
#endif
|
||||
|
||||
@@ -396,7 +396,7 @@ static const struct LoraDevDone lora_done =
|
||||
* @param bus_name spi bus name
|
||||
* @param dev_name spi dev name
|
||||
* @param drv_name spi drv name
|
||||
* @param flash_name flash dev name
|
||||
* @param lora_name lora name
|
||||
*/
|
||||
SpiLoraDeviceType SpiLoraInit(char *bus_name, char *dev_name, char *drv_name, char *lora_name)
|
||||
{
|
||||
@@ -493,7 +493,7 @@ int LoraSx12xxSpiDeviceInit(void)
|
||||
return EOK;
|
||||
}
|
||||
|
||||
//#define LORA_TEST
|
||||
#define LORA_TEST
|
||||
#ifdef LORA_TEST
|
||||
/*Just for lora test*/
|
||||
static struct Bus *bus;
|
||||
@@ -504,11 +504,11 @@ void LoraOpen(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
ret = LoraSx12xxSpiDeviceInit();
|
||||
if (EOK != ret) {
|
||||
KPrintf("LoraSx12xxSpiDeviceInit failed\n");
|
||||
return;
|
||||
}
|
||||
// ret = LoraSx12xxSpiDeviceInit();
|
||||
// if (EOK != ret) {
|
||||
// KPrintf("LoraSx12xxSpiDeviceInit failed\n");
|
||||
// return;
|
||||
// }
|
||||
|
||||
bus = BusFind(SPI_BUS_NAME_2);
|
||||
dev = BusFindDevice(bus, SX12XX_DEVICE_NAME);
|
||||
|
||||
@@ -103,7 +103,7 @@ static x_err_t Stm32SpiInit(struct Stm32Spi *SpiDrv, struct SpiMasterParam *cfg)
|
||||
|
||||
SPI_InitTypeDef *SpiInit = &SpiDrv->init;
|
||||
|
||||
if (cfg->spi_work_mode & DEV_SPI_SLAVE)
|
||||
if (cfg->spi_work_mode & SPI_DEV_SLAVE)
|
||||
{
|
||||
SpiInit->SPI_Mode = SPI_Mode_Slave;
|
||||
}
|
||||
|
||||
@@ -784,12 +784,12 @@ uint32_t SX1276LoraChannelEmpty( void )
|
||||
|
||||
if(result == RF_CHANNEL_EMPTY)
|
||||
{
|
||||
KPrintf("\nLora--信道可用(RF_CHANNEL_EMPTY)\n");
|
||||
KPrintf("\nLora--RF_CHANNEL_EMPTY\n");
|
||||
return 0;
|
||||
}
|
||||
else if(result == RF_CHANNEL_ACTIVITY_DETECTED)
|
||||
{
|
||||
KPrintf("\nLora--信道正被占用(RF_CHANNEL_ACTIVITY_DETECTED)\n");
|
||||
KPrintf("\nLora--RF_CHANNEL_ACTIVITY_DETECTED\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
config BSP_USING_STM32_USBH
|
||||
bool "Using usb host"
|
||||
default y
|
||||
default n
|
||||
if BSP_USING_STM32_USBH
|
||||
config USB_BUS_NAME
|
||||
string "usb bus name"
|
||||
@@ -11,5 +11,15 @@ config BSP_USING_STM32_USBH
|
||||
config USB_DEVICE_NAME
|
||||
string "usb bus device name"
|
||||
default "usb_dev"
|
||||
config MOUNT_USB_FS
|
||||
bool "mount usb file system"
|
||||
default y
|
||||
select MOUNT_USB
|
||||
|
||||
if MOUNT_USB_FS
|
||||
config MOUNT_USB_FS_TYPE
|
||||
int "choose file system type : FATFS(0) LWEXT4(3)"
|
||||
default 0
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
uint32 UdiskRead_new_api(void *dev, struct BusBlockReadParam *read_param);
|
||||
uint32 UdiskWirte_new_api(void *dev, struct BusBlockWriteParam *write_param);
|
||||
|
||||
#ifdef MOUNT_USB
|
||||
int MountUsb(void)
|
||||
{
|
||||
STM32USBHostRegister();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32 UdiskOpenNewApi(void *dev)
|
||||
{
|
||||
return EOK;
|
||||
|
||||
@@ -37,7 +37,7 @@ menu "aiit-riscv64-board feature"
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool "mount cd card"
|
||||
bool "mount sd card"
|
||||
default n
|
||||
select BSP_USING_SDIO
|
||||
config MOUNT_USB
|
||||
|
||||
@@ -71,7 +71,7 @@ extern int HwCh376Init(void);
|
||||
* @description: Mount USB
|
||||
* @return 0
|
||||
*/
|
||||
int MountUSB(void)
|
||||
int MountUsb(void)
|
||||
{
|
||||
if (MountFilesystem(USB_BUS_NAME, USB_DEVICE_NAME, USB_DRIVER_NAME, FSTYPE_CH376, "/") == 0)
|
||||
KPrintf("usb mount to '/'");
|
||||
|
||||
@@ -389,7 +389,7 @@ static const struct LoraDevDone lora_done =
|
||||
* @param bus_name spi bus name
|
||||
* @param dev_name spi dev name
|
||||
* @param drv_name spi drv name
|
||||
* @param flash_name flash dev name
|
||||
* @param lora_name lora name
|
||||
*/
|
||||
SpiLoraDeviceType SpiLoraInit(char *bus_name, char *dev_name, char *drv_name, char *lora_name)
|
||||
{
|
||||
|
||||
@@ -221,7 +221,7 @@ static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStand
|
||||
{
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
|
||||
|
||||
uint32 spi_read_length = 0;;
|
||||
uint32 spi_read_length = 0;
|
||||
uint8 device_id = dev_param->spi_slave_param->spi_slave_id;
|
||||
uint8 device_master_id = dev_param->spi_dma_param->spi_master_id;
|
||||
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
@@ -394,9 +394,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device2;
|
||||
memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2;
|
||||
static struct SpiSlaveParam spi_slaveparam2;
|
||||
memset(&spi_slaveparam2, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam2.spi_slave_id = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_slaveparam2.spi_cs_gpio_pin = SPI1_CS2_PIN;
|
||||
spi_slaveparam2.spi_cs_select_id = SPI_CHIP_SELECT_2;
|
||||
|
||||
spi_device2.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device2.spi_param.spi_slave_param = &spi_slaveparam2;
|
||||
|
||||
spi_device2.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
@@ -417,9 +423,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device3;
|
||||
memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3;
|
||||
static struct SpiSlaveParam spi_slaveparam3;
|
||||
memset(&spi_slaveparam3, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam3.spi_slave_id = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_slaveparam3.spi_cs_gpio_pin = SPI1_CS3_PIN;
|
||||
spi_slaveparam3.spi_cs_select_id = SPI_CHIP_SELECT_3;
|
||||
|
||||
spi_device3.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device3.spi_param.spi_slave_param = &spi_slaveparam3;
|
||||
|
||||
spi_device3.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
|
||||
@@ -784,12 +784,12 @@ uint32_t SX1276LoraChannelEmpty( void )
|
||||
|
||||
if(result == RF_CHANNEL_EMPTY)
|
||||
{
|
||||
KPrintf("\nLora--信道可用(RF_CHANNEL_EMPTY)\n");
|
||||
KPrintf("\nLora--RF_CHANNEL_EMPTY\n");
|
||||
return 0;
|
||||
}
|
||||
else if(result == RF_CHANNEL_ACTIVITY_DETECTED)
|
||||
{
|
||||
KPrintf("\nLora--信道正被占用(RF_CHANNEL_ACTIVITY_DETECTED)\n");
|
||||
KPrintf("\nLora--RF_CHANNEL_ACTIVITY_DETECTED)\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -68,7 +68,7 @@ extern int HwSpiInit(void);
|
||||
* @description: Mount USB
|
||||
* @return 0
|
||||
*/
|
||||
int MountUSB(void)
|
||||
int MountUsb(void)
|
||||
{
|
||||
if (MountFilesystem(USB_BUS_NAME, USB_DEVICE_NAME, USB_DRIVER_NAME, FSTYPE_CH376, "/") == 0)
|
||||
KPrintf("usb mount to '/'\n");
|
||||
|
||||
@@ -28,6 +28,12 @@ menu "hc32f4a0 feature"
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
config MOUNT_SDCARD
|
||||
bool
|
||||
default n
|
||||
config MOUNT_USB
|
||||
bool
|
||||
default n
|
||||
endmenu
|
||||
|
||||
menu "Hardware feature"
|
||||
|
||||
@@ -34,6 +34,18 @@ Modification:
|
||||
#include <hc32_ll.h>
|
||||
#include <connect_usart.h>
|
||||
|
||||
#ifdef BSP_USING_SDIO
|
||||
#include <connect_sdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SPI
|
||||
#include <connect_spi.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_USB
|
||||
#include <connect_usb.h>
|
||||
#endif
|
||||
|
||||
extern void entry(void);
|
||||
extern int HwUsartInit();
|
||||
|
||||
@@ -46,15 +58,10 @@ void SystemClockConfig(void)
|
||||
stc_clock_xtal_init_t stcXtalInit;
|
||||
stc_clock_pll_init_t stcPLLHInit;
|
||||
|
||||
/* PCLK0, HCLK Max 240MHz */
|
||||
/* PCLK1, PCLK4 Max 120MHz */
|
||||
/* PCLK2, PCLK3 Max 60MHz */
|
||||
/* EX BUS Max 120MHz */
|
||||
CLK_SetClockDiv(CLK_BUS_CLK_ALL, \
|
||||
(CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
|
||||
CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
|
||||
CLK_SetClockDiv(CLK_BUS_CLK_ALL,
|
||||
(CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 |
|
||||
CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 |
|
||||
CLK_HCLK_DIV1));
|
||||
|
||||
(void)CLK_XtalStructInit(&stcXtalInit);
|
||||
/* Config Xtal and enable Xtal */
|
||||
stcXtalInit.u8Mode = CLK_XTAL_MD_OSC;
|
||||
@@ -64,26 +71,37 @@ void SystemClockConfig(void)
|
||||
(void)CLK_XtalInit(&stcXtalInit);
|
||||
|
||||
(void)CLK_PLLStructInit(&stcPLLHInit);
|
||||
|
||||
stcPLLHInit.u8PLLState = CLK_PLL_ON;
|
||||
stcPLLHInit.PLLCFGR = 0UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
|
||||
|
||||
#ifdef BSP_USING_USB
|
||||
/* VCO = (8/1)*120 = 960MHz*/
|
||||
stcPLLHInit.u8PLLState = CLK_PLL_ON;
|
||||
stcPLLHInit.PLLCFGR = 0UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
|
||||
#else
|
||||
/* VCO = (8/1)*100 = 800MHz*/
|
||||
stcPLLHInit.PLLCFGR_f.PLLN = 100UL - 1UL;
|
||||
#endif
|
||||
stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
|
||||
(void)CLK_PLLInit(&stcPLLHInit);
|
||||
|
||||
#ifdef BSP_USING_USB
|
||||
/* Highspeed SRAM set to 0 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0);
|
||||
|
||||
/* SRAM1_2_3_4_backup set to 1 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle((SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB), SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1);
|
||||
|
||||
#else
|
||||
/* Highspeed SRAM set to 1 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1);
|
||||
/* SRAM1_2_3_4_backup set to 2 Read/Write wait cycle */
|
||||
SRAM_SetWaitCycle((SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB), SRAM_WAIT_CYCLE2, SRAM_WAIT_CYCLE2);
|
||||
#endif
|
||||
/* 0-wait @ 40MHz */
|
||||
(void)EFM_SetWaitCycle(EFM_WAIT_CYCLE5);
|
||||
|
||||
EFM_SetWaitCycle(EFM_WAIT_CYCLE5);
|
||||
/* 4 cycles for 200 ~ 250MHz */
|
||||
GPIO_SetReadWaitCycle(GPIO_RD_WAIT4);
|
||||
CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL);
|
||||
@@ -98,7 +116,7 @@ void PeripheralClockConfig(void)
|
||||
CLK_SetCANClockSrc(CLK_CAN2, CLK_CANCLK_SYSCLK_DIV6);
|
||||
#endif
|
||||
|
||||
#if defined(RT_USING_ADC)
|
||||
#if defined(BSP_USING_ADC)
|
||||
CLK_SetPeriClockSrc(CLK_PERIPHCLK_PCLK);
|
||||
#endif
|
||||
}
|
||||
@@ -117,12 +135,26 @@ void SysTickConfiguration(void)
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
TickAndTaskTimesliceUpdate();
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
|
||||
struct InitSequenceDesc _board_init[] =
|
||||
{
|
||||
{ " NONE ",NONE },
|
||||
{
|
||||
#ifdef BSP_USING_SDIO
|
||||
{ "sdio", HwSdioInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_SPI
|
||||
{ "spi", HwSpiInit },
|
||||
#endif
|
||||
#ifdef BSP_USING_USB
|
||||
{ "usb", HwUsbHostInit },
|
||||
#endif
|
||||
{ " NONE ", NONE },
|
||||
};
|
||||
|
||||
void InitBoardHardware()
|
||||
|
||||
@@ -35,11 +35,11 @@ Modification:
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int __bss_end;
|
||||
extern int __heap_start;
|
||||
extern unsigned int g_service_table_start;
|
||||
extern unsigned int g_service_table_end;
|
||||
|
||||
#define MEMORY_START_ADDRESS (&__bss_end)
|
||||
#define MEMORY_START_ADDRESS (&__heap_start)
|
||||
#define HC32F4_SRAM_SIZE 512
|
||||
#define MEMORY_END_ADDRESS (0x1FFE0000 + HC32F4_SRAM_SIZE * 1024)
|
||||
|
||||
|
||||
@@ -216,20 +216,18 @@ SECTIONS
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
PROVIDE(_end = .);
|
||||
*(.heap*)
|
||||
. = ALIGN(8);
|
||||
__HeapLimit = .;
|
||||
|
||||
__StackLimit = .;
|
||||
*(.stack*)
|
||||
. = ALIGN(8);
|
||||
__StackTop = .;
|
||||
|
||||
__heap_start = .;
|
||||
} >RAM
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
|
||||
PROVIDE(_stack = __StackTop);
|
||||
PROVIDE(_Min_Heap_Size = __HeapLimit - __HeapBase);
|
||||
PROVIDE(_Min_Stack_Size = __StackTop - __StackLimit);
|
||||
|
||||
__RamEnd = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
@@ -5,3 +5,27 @@ menuconfig BSP_USING_UART
|
||||
if BSP_USING_UART
|
||||
source "$BSP_DIR/third_party_driver/usart/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_SPI
|
||||
bool "Using SPI device"
|
||||
default n
|
||||
select RESOURCES_SPI
|
||||
if BSP_USING_SPI
|
||||
source "$BSP_DIR/third_party_driver/spi/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_SDIO
|
||||
bool "Using SD CARD device"
|
||||
default n
|
||||
select RESOURCES_SDIO
|
||||
if BSP_USING_SDIO
|
||||
source "$BSP_DIR/third_party_driver/sdio/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_USB
|
||||
bool "Using USB device"
|
||||
default n
|
||||
select RESOURCES_USB
|
||||
if BSP_USING_USB
|
||||
source "$BSP_DIR/third_party_driver/usb/Kconfig"
|
||||
endif
|
||||
|
||||
@@ -4,4 +4,16 @@ ifeq ($(CONFIG_BSP_USING_UART),y)
|
||||
SRC_DIR += usart
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_DIR += spi
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SDIO),y)
|
||||
SRC_DIR += sdio
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_USB),y)
|
||||
SRC_DIR += usb
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -101,7 +101,7 @@ extern "C"
|
||||
#define LL_TMRA_ENABLE (DDL_ON)
|
||||
#define LL_TRNG_ENABLE (DDL_ON)
|
||||
#define LL_USART_ENABLE (DDL_ON)
|
||||
#define LL_USB_ENABLE (DDL_OFF)
|
||||
#define LL_USB_ENABLE (DDL_ON)
|
||||
#define LL_VREF_ENABLE (DDL_OFF)
|
||||
#define LL_WDT_ENABLE (DDL_ON)
|
||||
|
||||
|
||||
@@ -4,4 +4,16 @@ ifeq ($(CONFIG_BSP_USING_UART),y)
|
||||
SRC_FILES += hc32_ll_usart.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SDIO),y)
|
||||
SRC_FILES += hc32_ll_sdioc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SPI),y)
|
||||
SRC_FILES += hc32_ll_spi.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_USB),y)
|
||||
SRC_FILES += hc32_ll_usb.c
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_sdio.h
|
||||
* @brief define hc32f4a0-board sdio function and struct
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-15
|
||||
*/
|
||||
|
||||
#ifndef CONNECT_SDIO_H
|
||||
#define CONNECT_SDIO_H
|
||||
|
||||
#include <device.h>
|
||||
#include <hc32_ll_gpio.h>
|
||||
#include <hc32_ll_fcg.h>
|
||||
#include <hc32_ll_sdioc.h>
|
||||
#include <hardware_sdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SD_CARD_STACK_SIZE 2048
|
||||
|
||||
int HwSdioInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_spi.h
|
||||
* @brief define hc32f4a0-board spi function and struct
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-17
|
||||
*/
|
||||
|
||||
#ifndef CONNECT_SPI_H
|
||||
#define CONNECT_SPI_H
|
||||
|
||||
#include <device.h>
|
||||
#include <hardware_irq.h>
|
||||
#include <hc32_ll_spi.h>
|
||||
#include <hc32_ll_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int HwSpiInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_spi_lora.h
|
||||
* @brief define spi lora dev function and struct using bus driver framework
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-31
|
||||
*/
|
||||
|
||||
#ifndef CONNECT_SPI_LORA_H
|
||||
#define CONNECT_SPI_LORA_H
|
||||
|
||||
#include <device.h>
|
||||
#include <hc32_ll_utility.h>
|
||||
#include <connect_spi.h>
|
||||
#include <radio.h>
|
||||
#include <spi_lora_sx12xx.h>
|
||||
#include <sx1276.h>
|
||||
#include <sx1276-Hal.h>
|
||||
#include <sx1276-LoRa.h>
|
||||
#include <sx1276-LoRaMisc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//#define SPI_LORA_FREQUENCY 10000000
|
||||
#define SPI_LORA_BUFFER_SIZE 256
|
||||
|
||||
typedef struct SpiLoraDevice *SpiLoraDeviceType;
|
||||
|
||||
struct LoraDevDone
|
||||
{
|
||||
uint32 (*open) (void *dev);
|
||||
uint32 (*close) (void *dev);
|
||||
uint32 (*write) (void *dev, struct BusBlockWriteParam *write_param);
|
||||
uint32 (*read) (void *dev, struct BusBlockReadParam *read_param);
|
||||
};
|
||||
|
||||
struct SpiLoraDevice
|
||||
{
|
||||
struct SpiHardwareDevice *spi_dev;
|
||||
struct SpiHardwareDevice lora_dev;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_usb.h
|
||||
* @brief define hc32f4a0-board usb function and struct
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-07
|
||||
*/
|
||||
|
||||
#ifndef CONNECT_USB_H
|
||||
#define CONNECT_USB_H
|
||||
|
||||
#include <device.h>
|
||||
#include <hc32_ll_utility.h>
|
||||
#include <hc32_ll_gpio.h>
|
||||
#include <usb_lib.h>
|
||||
#include <usb_host_user.h>
|
||||
#include <usb_host_driver.h>
|
||||
#include <usb_host_core.h>
|
||||
#include <usb_host_msc_class.h>
|
||||
#include <usb_host_msc_scsi.h>
|
||||
#include <usb_host_msc_bot.h>
|
||||
#include <usb_host_int.h>
|
||||
|
||||
#if defined(FS_VFS)
|
||||
#include <iot-vfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USB_HOST_STACK_SIZE 4096
|
||||
|
||||
#define USB_SINGLE_BLOCK_SIZE 512
|
||||
|
||||
int HwUsbHostInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file sdioc/sdioc_sd/source/sd.h
|
||||
* @brief This file contains all the functions prototypes of the Secure
|
||||
* Digital(SD) driver library.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hardware_sdio.h
|
||||
* @brief define hc32f4a0-board sdio function and struct
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-18
|
||||
*/
|
||||
|
||||
#ifndef __HARDWARE_SDIO_H__
|
||||
#define __HARDWARE_SDIO_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "hc32_ll_sdioc.h"
|
||||
#include "hc32_ll_dma.h"
|
||||
#include "hc32_ll_utility.h"
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Examples
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup SDIOC_SD_Card
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @defgroup SD_Global_Types SD Global Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SD Card State enumeration structure definition
|
||||
*/
|
||||
typedef enum {
|
||||
SD_CARD_STAT_IDLE = 0x00U, /*!< Card state is idle */
|
||||
SD_CARD_STAT_RDY = 0x01U, /*!< Card state is ready */
|
||||
SD_CARD_STAT_IDENTIFY = 0x02U, /*!< Card is in identification state */
|
||||
SD_CARD_STAT_STANDBY = 0x03U, /*!< Card is in standby state */
|
||||
SD_CARD_STAT_TRANS = 0x04U, /*!< Card is in transfer state */
|
||||
SD_CARD_STAT_TX_DATA = 0x05U, /*!< Card is sending an operation */
|
||||
SD_CARD_STAT_RX_DATA = 0x06U, /*!< Card is receiving operation information */
|
||||
SD_CARD_STAT_PGM = 0x07U, /*!< Card is in programming state */
|
||||
SD_CARD_STAT_DISCONNECT = 0x08U /*!< Card is disconnected */
|
||||
} en_sd_card_state_t;
|
||||
|
||||
/**
|
||||
* @brief SD Card Information Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t u32CardType; /*!< Specifies the card Type */
|
||||
uint32_t u32CardVersion; /*!< Specifies the card version */
|
||||
uint32_t u32Class; /*!< Specifies the class of the card class */
|
||||
uint32_t u32RelativeCardAddr; /*!< Specifies the Relative Card Address */
|
||||
uint32_t u32BlockNum; /*!< Specifies the Card Capacity in blocks */
|
||||
uint32_t u32BlockSize; /*!< Specifies one block size in bytes */
|
||||
uint32_t u32LogBlockNum; /*!< Specifies the Card logical Capacity in blocks */
|
||||
uint32_t u32LogBlockSize; /*!< Specifies logical block size in bytes */
|
||||
} stc_sd_card_info_t;
|
||||
|
||||
/**
|
||||
* @brief SD Card Specific Data(CSD Register) Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t u8CSDStruct; /*!< CSD structure */
|
||||
uint8_t u8Reserved1; /*!< Reserved */
|
||||
uint8_t u8TAAC; /*!< Data read access time 1 */
|
||||
uint8_t u8NSAC; /*!< Data read access time 2 in CLK cycles */
|
||||
uint8_t u8MaxBusClkFreq; /*!< Max. bus clock frequency */
|
||||
uint16_t u16CardCmdClass; /*!< Card command classes */
|
||||
uint8_t u8ReadBlockLen; /*!< Max. read data block length */
|
||||
uint8_t u8BlockReadPartial; /*!< Partial blocks for read allowed */
|
||||
uint8_t u8WriteBlockMisalign; /*!< Write block misalignment */
|
||||
uint8_t u8ReadBlockMisalign; /*!< Read block misalignment */
|
||||
uint8_t u8DSRImplement; /*!< DSR implemented */
|
||||
uint8_t u8Reserved2; /*!< Reserved */
|
||||
uint32_t u32DeviceSize; /*!< Device Size */
|
||||
uint8_t u8MaxReadCurrVDDMin; /*!< Max. read current @ VDD min */
|
||||
uint8_t u8MaxReadCurrVDDMax; /*!< Max. read current @ VDD max */
|
||||
uint8_t u8MaxWriteCurrVDDMin; /*!< Max. write current @ VDD min */
|
||||
uint8_t u8MaxWriteCurrVDDMax; /*!< Max. write current @ VDD max */
|
||||
uint8_t u8DeviceSizeMul; /*!< Device size multiplier */
|
||||
uint8_t u8EraseSingleBlockEn; /*!< Erase single block enable */
|
||||
uint8_t u8EraseSectorSize; /*!< Erase sector size */
|
||||
uint8_t u8WriteProtectGroupSize; /*!< Write protect group size */
|
||||
uint8_t u8WriteProtectGroupEn; /*!< Write protect group enable */
|
||||
uint8_t u8Reserved3; /*!< Reserved */
|
||||
uint8_t u8WriteSpeedFactor; /*!< Write speed factor */
|
||||
uint8_t u8MaxWriteBlockLen; /*!< Max. write data block length */
|
||||
uint8_t u8WriteBlockPartial; /*!< Partial blocks for write allowed */
|
||||
uint8_t u8Reserved4; /*!< Reserved */
|
||||
uint8_t u8FileFormatGroup; /*!< File format group */
|
||||
uint8_t u8CopyFlag; /*!< Copy flag (OTP) */
|
||||
uint8_t u8PermWriteProtect; /*!< Permanent write protection */
|
||||
uint8_t u8TempWriteProtect; /*!< Temporary write protection */
|
||||
uint8_t u8FileFormat; /*!< File format */
|
||||
uint8_t u8Reserved5; /*!< Reserved */
|
||||
uint8_t u8CRCChecksum; /*!< CSD CRC7 checksum */
|
||||
uint8_t u8Reserved6; /*!< Always 1 */
|
||||
} stc_sd_card_csd_t;
|
||||
|
||||
/**
|
||||
* @brief SD Card Identification Data(CID Register) Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t u8ManufacturerID; /*!< Manufacturer ID */
|
||||
uint16_t u16OemAppID; /*!< OEM/Application ID */
|
||||
uint32_t u32ProductName1; /*!< Product Name part1 */
|
||||
uint8_t u8ProductName2; /*!< Product Name part2 */
|
||||
uint8_t u8ProductRevision; /*!< Product Revision */
|
||||
uint32_t u32ProductSN; /*!< Product Serial Number */
|
||||
uint8_t u8Reserved1; /*!< Reserved1 */
|
||||
uint16_t u16ManufactDate; /*!< Manufacturing Date */
|
||||
uint8_t u8CRCChecksum; /*!< CRC7 checksum */
|
||||
uint8_t u8Reserved2; /*!< Always 1 */
|
||||
} stc_sd_card_cid_t;
|
||||
|
||||
/**
|
||||
* @brief SD Card Status Structure definition (returned by ACMD13)
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t u8DataBusWidth; /*!< Shows the currently defined data bus width */
|
||||
uint8_t u8SecuredMode; /*!< Card is in secured mode of operation */
|
||||
uint16_t u16CardType; /*!< Carries information about card type */
|
||||
uint32_t u32ProtectedAreaSize; /*!< Carries information about the capacity of protected area */
|
||||
uint8_t u8SpeedClass; /*!< Carries information about the speed class of the card */
|
||||
uint8_t u8PerformanceMove; /*!< Carries information about the card's performance move */
|
||||
uint8_t u8AllocUnitSize; /*!< Carries information about the card's allocation unit size */
|
||||
uint16_t u16EraseSize; /*!< Determines the number of AUs to be erased in one operation */
|
||||
uint8_t u8EraseTimeout; /*!< Determines the timeout for any number of AU erase */
|
||||
uint8_t u8EraseOffset; /*!< Carries information about the erase offset */
|
||||
} stc_sd_card_status_t;
|
||||
|
||||
/**
|
||||
* @brief SD handle Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
CM_SDIOC_TypeDef *SDIOCx; /*!< Pointer to SDIOC registers base address */
|
||||
stc_sdioc_init_t stcSdiocInit; /*!< SDIOC Initialize structure @ref stc_sdioc_init_t */
|
||||
CM_DMA_TypeDef *DMAx; /*!< Pointer to DMA registers base address */
|
||||
uint8_t u8DmaTxCh; /*!< Specifies the DMA channel used to send */
|
||||
uint8_t u8DmaRxCh; /*!< Specifies the DMA channel used to receive */
|
||||
uint8_t *pu8Buffer; /*!< Pointer to SD Tx/Rx transfer Buffer */
|
||||
uint32_t u32Len; /*!< SD Tx/Rx Transfer length */
|
||||
uint32_t u32Context; /*!< SD transfer context */
|
||||
uint32_t u32ErrorCode; /*!< SD Card Error codes */
|
||||
stc_sd_card_info_t stcSdCardInfo; /*!< SD Card information */
|
||||
uint32_t u32CSD[4]; /*!< SD card specific data table */
|
||||
uint32_t u32CID[4]; /*!< SD card identification number table */
|
||||
uint32_t u32SCR[2]; /*!< SD Configuration Register table */
|
||||
} stc_sd_handle_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @defgroup SD_Global_Macros SD Global Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup SD_Transfer_Context SD Transfer Context
|
||||
* @{
|
||||
*/
|
||||
#define SD_CONTEXT_NONE (0x00UL) /*!< None */
|
||||
#define SD_CONTEXT_RD_SINGLE_BLOCK (0x01UL) /*!< Read single block operation */
|
||||
#define SD_CONTEXT_RD_MULTI_BLOCK (0x02UL) /*!< Read multiple blocks operation */
|
||||
#define SD_CONTEXT_WR_SINGLE_BLOCK (0x10UL) /*!< Write single block operation */
|
||||
#define SD_CONTEXT_WR_MULTI_BLOCK (0x20UL) /*!< Write multiple blocks operation */
|
||||
#define SD_CONTEXT_INT (0x40UL) /*!< Process in Interrupt mode */
|
||||
#define SD_CONTEXT_DMA (0x80UL) /*!< Process in DMA mode */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup SD_Support_Memory_Card SD Support Memory Card
|
||||
* @{
|
||||
*/
|
||||
#define SD_CARD_SDSC (0x00UL)
|
||||
#define SD_CARD_SDHC_SDXC (0x01UL)
|
||||
#define SD_CARD_SECURED (0x03UL)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup SD_Support_Version SD Support Version
|
||||
* @{
|
||||
*/
|
||||
#define SD_CARD_V1_X (0x00UL) /*!< SD Card version: 1.x */
|
||||
#define SD_CARD_V2_X (0x01UL) /*!< SD Card version: 2.x */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup SD_Global_Functions
|
||||
* @{
|
||||
*/
|
||||
int32_t SD_DeInit(stc_sd_handle_t *handle);
|
||||
int32_t SD_Init(stc_sd_handle_t *handle);
|
||||
int32_t SD_GetCardState(stc_sd_handle_t *handle, en_sd_card_state_t *peCardState);
|
||||
int32_t SD_GetCardCID(const stc_sd_handle_t *handle, stc_sd_card_cid_t *pstcCardCID);
|
||||
int32_t SD_GetCardCSD(stc_sd_handle_t *handle, stc_sd_card_csd_t *pstcCardCSD);
|
||||
int32_t SD_GetCardStatus(stc_sd_handle_t *handle, stc_sd_card_status_t *pstcCardStatus);
|
||||
int32_t SD_GetCardInfo(stc_sd_handle_t *handle, stc_sd_card_info_t *pstcCardInfo);
|
||||
int32_t SD_GetErrorCode(const stc_sd_handle_t *handle, uint32_t *pu32ErrorCode);
|
||||
|
||||
/* Callback in non blocking modes */
|
||||
void SD_IRQHandler(stc_sd_handle_t *handle);
|
||||
void SD_TxCompleteCallback(stc_sd_handle_t *handle);
|
||||
void SD_RxCompleteCallback(stc_sd_handle_t *handle);
|
||||
void SD_ErrorCallback(stc_sd_handle_t *handle);
|
||||
|
||||
/* Polling Mode */
|
||||
int32_t SD_Erase(stc_sd_handle_t *handle, uint32_t u32BlockStartAddr, uint32_t u32BlockEndAddr);
|
||||
int32_t SD_ReadBlocks(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount,
|
||||
uint8_t *pu8Data, uint32_t u32Timeout);
|
||||
int32_t SD_WriteBlocks(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount,
|
||||
uint8_t *pu8Data, uint32_t u32Timeout);
|
||||
/* Interrupt Mode */
|
||||
int32_t SD_ReadBlocks_INT(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount, uint8_t *pu8Data);
|
||||
int32_t SD_WriteBlocks_INT(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount, uint8_t *pu8Data);
|
||||
/* DMA Mode */
|
||||
int32_t SD_ReadBlocks_DMA(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount, uint8_t *pu8Data);
|
||||
int32_t SD_WriteBlocks_DMA(stc_sd_handle_t *handle, uint32_t u32BlockAddr, uint16_t u16BlockCount, uint8_t *pu8Data);
|
||||
/* Abort */
|
||||
int32_t SD_Abort(stc_sd_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SD_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,24 @@
|
||||
if BSP_USING_SDIO
|
||||
config SDIO_BUS_NAME
|
||||
string "sdio bus name"
|
||||
default "sdio"
|
||||
|
||||
config SDIO_DRIVER_NAME
|
||||
string "sdio driver name"
|
||||
default "sdio_drv"
|
||||
|
||||
config SDIO_DEVICE_NAME
|
||||
string "sdio device name"
|
||||
default "sdio_dev"
|
||||
|
||||
config MOUNT_SDCARD_FS
|
||||
bool "mount sd card file system : if y then not support usb-mount-fs"
|
||||
default y
|
||||
select MOUNT_SDCARD
|
||||
|
||||
if MOUNT_SDCARD_FS
|
||||
config MOUNT_SDCARD_FS_TYPE
|
||||
int "choose file system type : FATFS(0)"
|
||||
default 0
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := connect_sdio.c hardware_sdio.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file sdioc/sdioc_sd/source/main.c
|
||||
* @brief Main program of SDIOC SD card for the Device Driver Library.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_sdio.c
|
||||
* @brief support sdio function using bus driver framework on hc32f4a0 board
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-18
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: connect_sdio.c
|
||||
Description: support hc32f4a0-board sd card configure and sdio bus register function
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-01-24
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support hc32f4a0-board sdio configure, write and read
|
||||
2. support hc32f4a0-board sdio bus device and driver register
|
||||
*************************************************/
|
||||
|
||||
#include <connect_sdio.h>
|
||||
|
||||
/* SD transfer mode */
|
||||
#define SD_TRANS_MD_POLLING (0U)
|
||||
#define SD_TRANS_MD_INT (1U)
|
||||
#define SD_TRANS_MD_DMA (2U)
|
||||
/* Populate the following macro with an value, reference "SD transfer mode" */
|
||||
#define SD_TRANS_MD (SD_TRANS_MD_POLLING)
|
||||
|
||||
/* SDIOC configuration define */
|
||||
#define SDIOC_SD_UINT (CM_SDIOC1)
|
||||
#define SDIOC_SD_CLK (FCG1_PERIPH_SDIOC1)
|
||||
|
||||
/* CD = PB13 */
|
||||
#define SDIOC_CD_PORT (GPIO_PORT_B)
|
||||
#define SDIOC_CD_PIN (GPIO_PIN_13)
|
||||
/* CK = PC12 */
|
||||
#define SDIOC_CK_PORT (GPIO_PORT_C)
|
||||
#define SDIOC_CK_PIN (GPIO_PIN_12)
|
||||
/* CMD = PD02 */
|
||||
#define SDIOC_CMD_PORT (GPIO_PORT_D)
|
||||
#define SDIOC_CMD_PIN (GPIO_PIN_02)
|
||||
/* D0 = PB07 */
|
||||
#define SDIOC_D0_PORT (GPIO_PORT_B)
|
||||
#define SDIOC_D0_PIN (GPIO_PIN_07)
|
||||
/* D1 = PA08 */
|
||||
#define SDIOC_D1_PORT (GPIO_PORT_A)
|
||||
#define SDIOC_D1_PIN (GPIO_PIN_08)
|
||||
/* D2 = PC10 */
|
||||
#define SDIOC_D2_PORT (GPIO_PORT_C)
|
||||
#define SDIOC_D2_PIN (GPIO_PIN_10)
|
||||
/* D3 = PB05 */
|
||||
#define SDIOC_D3_PORT (GPIO_PORT_B)
|
||||
#define SDIOC_D3_PIN (GPIO_PIN_05)
|
||||
|
||||
static stc_sd_handle_t gSdHandle;
|
||||
static int sd_lock = -1;
|
||||
|
||||
static void SdCardConfig(void)
|
||||
{
|
||||
/* Enable SDIOC clock */
|
||||
FCG_Fcg1PeriphClockCmd(SDIOC_SD_CLK, ENABLE);
|
||||
|
||||
/* SDIOC pins configuration */
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinState = PIN_STAT_RST;
|
||||
stcGpioInit.u16PinDir = PIN_DIR_IN;
|
||||
(void)GPIO_Init(SDIOC_CD_PORT, SDIOC_CD_PIN, &stcGpioInit);
|
||||
|
||||
GPIO_SetFunc(SDIOC_CK_PORT, SDIOC_CK_PIN, GPIO_FUNC_9);
|
||||
GPIO_SetFunc(SDIOC_CMD_PORT, SDIOC_CMD_PIN, GPIO_FUNC_9);
|
||||
GPIO_SetFunc(SDIOC_D0_PORT, SDIOC_D0_PIN, GPIO_FUNC_9);
|
||||
GPIO_SetFunc(SDIOC_D1_PORT, SDIOC_D1_PIN, GPIO_FUNC_9);
|
||||
GPIO_SetFunc(SDIOC_D2_PORT, SDIOC_D2_PIN, GPIO_FUNC_9);
|
||||
GPIO_SetFunc(SDIOC_D3_PORT, SDIOC_D3_PIN, GPIO_FUNC_9);
|
||||
|
||||
/* Configure structure initialization */
|
||||
gSdHandle.SDIOCx = SDIOC_SD_UINT;
|
||||
gSdHandle.stcSdiocInit.u32Mode = SDIOC_MD_SD;
|
||||
gSdHandle.stcSdiocInit.u8CardDetect = SDIOC_CARD_DETECT_CD_PIN_LVL;
|
||||
gSdHandle.stcSdiocInit.u8SpeedMode = SDIOC_SPEED_MD_HIGH;
|
||||
gSdHandle.stcSdiocInit.u8BusWidth = SDIOC_BUS_WIDTH_4BIT;
|
||||
gSdHandle.stcSdiocInit.u16ClockDiv = SDIOC_CLK_DIV2;
|
||||
gSdHandle.DMAx = NULL;
|
||||
}
|
||||
|
||||
static uint32 SdioConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
NULL_PARAM_CHECK(configure_info);
|
||||
|
||||
if (configure_info->configure_cmd == OPER_BLK_GETGEOME) {
|
||||
NULL_PARAM_CHECK(configure_info->private_data);
|
||||
struct DeviceBlockArrange *args = (struct DeviceBlockArrange *)configure_info->private_data;
|
||||
|
||||
args->size_perbank = gSdHandle.stcSdCardInfo.u32BlockSize;
|
||||
args->block_size = gSdHandle.stcSdCardInfo.u32BlockSize;
|
||||
args->bank_num = gSdHandle.stcSdCardInfo.u32BlockNum;
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SdioOpen(void *dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
if(sd_lock >= 0) {
|
||||
KSemaphoreDelete(sd_lock);
|
||||
}
|
||||
sd_lock = KSemaphoreCreate(1);
|
||||
if (sd_lock < 0){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SdioClose(void *dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
KSemaphoreDelete(sd_lock);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SdioRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
{
|
||||
uint8 ret = EOK;
|
||||
uint32 sector = read_param->pos;
|
||||
uint32 block_num = read_param->size;
|
||||
uint8 *read_buffer = (uint8 *)read_param->buffer;
|
||||
|
||||
KSemaphoreObtain(sd_lock, WAITING_FOREVER);
|
||||
|
||||
if (LL_OK != SD_ReadBlocks(&gSdHandle, sector, block_num, read_buffer, 2000UL)) {
|
||||
KPrintf("Read data blocks failed.\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KSemaphoreAbandon(sd_lock);
|
||||
|
||||
return read_param->size;
|
||||
}
|
||||
|
||||
static uint32 SdioWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||
{
|
||||
uint8 ret = EOK;
|
||||
uint32 sector = write_param->pos;
|
||||
uint32 block_num = write_param->size;
|
||||
uint8 *write_buffer = (uint8 *)write_param->buffer;
|
||||
|
||||
KSemaphoreObtain(sd_lock, WAITING_FOREVER);
|
||||
|
||||
if (LL_OK != SD_WriteBlocks(&gSdHandle, sector, block_num, write_buffer, 2000U)) {
|
||||
KPrintf("Write data blocks failed.\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KSemaphoreAbandon(sd_lock);
|
||||
|
||||
return write_param->size;
|
||||
}
|
||||
|
||||
static int SdioControl(struct HardwareDev *dev, struct HalDevBlockParam *block_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
if (OPER_BLK_GETGEOME == block_param->cmd) {
|
||||
block_param->dev_block.size_perbank = gSdHandle.stcSdCardInfo.u32BlockSize;
|
||||
block_param->dev_block.block_size = gSdHandle.stcSdCardInfo.u32BlockSize;
|
||||
block_param->dev_block.bank_num = gSdHandle.stcSdCardInfo.u32BlockNum;
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static struct SdioDevDone dev_done =
|
||||
{
|
||||
SdioOpen,
|
||||
SdioClose,
|
||||
SdioWrite,
|
||||
SdioRead,
|
||||
};
|
||||
|
||||
#if defined(FS_VFS) && defined(MOUNT_SDCARD_FS)
|
||||
#include <iot-vfs.h>
|
||||
|
||||
/**
|
||||
* @description: Mount SD card
|
||||
* @return 0
|
||||
*/
|
||||
static int MountSDCardFs(enum FilesystemType fs_type)
|
||||
{
|
||||
if (MountFilesystem(SDIO_BUS_NAME, SDIO_DEVICE_NAME, SDIO_DRIVER_NAME, fs_type, "/") == 0)
|
||||
KPrintf("Sd card mount to '/'");
|
||||
else
|
||||
KPrintf("Sd card mount to '/' failed!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SdCardAttach(void)
|
||||
{
|
||||
static stc_sd_handle_t *sd_handle = &gSdHandle;
|
||||
|
||||
KPrintf("\r\nCard inserted.\r\n");
|
||||
|
||||
/* Reset and init SDIOC */
|
||||
if (LL_OK != SDIOC_SWReset(sd_handle->SDIOCx, SDIOC_SW_RST_ALL)) {
|
||||
KPrintf("Reset SDIOC failed!\r\n");
|
||||
} else if (LL_OK != SD_Init(sd_handle)) {
|
||||
KPrintf("SD card initialize failed!\r\n");
|
||||
} else {
|
||||
KPrintf("SD card init done!\r\n");
|
||||
}
|
||||
|
||||
#ifdef MOUNT_SDCARD_FS
|
||||
/*mount file system*/
|
||||
MountSDCardFs(MOUNT_SDCARD_FS_TYPE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SdCardDetach(void)
|
||||
{
|
||||
/*unmount file system*/
|
||||
KPrintf("\r\nCard detect extracted.\r\n");
|
||||
|
||||
#ifdef MOUNT_SDCARD_FS
|
||||
UnmountFileSystem("/");
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8 SdCardReadCd(void)
|
||||
{
|
||||
en_pin_state_t sd_cd_state = GPIO_ReadInputPins(SDIOC_CD_PORT, SDIOC_CD_PIN);
|
||||
|
||||
if (PIN_RESET == sd_cd_state) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void SdCardTask(void* parameter)
|
||||
{
|
||||
static int sd_card_status = 0;
|
||||
|
||||
while (1) {
|
||||
if (!SdCardReadCd()) {
|
||||
if (!sd_card_status) {
|
||||
SdCardAttach();
|
||||
sd_card_status = 1;
|
||||
}
|
||||
} else {
|
||||
if (sd_card_status) {
|
||||
SdCardDetach();
|
||||
sd_card_status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOUNT_SDCARD
|
||||
int MountSDCard()
|
||||
{
|
||||
int sd_card_task = 0;
|
||||
sd_card_task = KTaskCreate("sd_card", SdCardTask, NONE,
|
||||
SD_CARD_STACK_SIZE, 8);
|
||||
if(sd_card_task < 0) {
|
||||
KPrintf("sd_card_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
StartupKTask(sd_card_task);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int HwSdioInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
static struct SdioBus sdio_bus;
|
||||
static struct SdioDriver sdio_drv;
|
||||
static struct SdioHardwareDevice sdio_dev;
|
||||
|
||||
memset(&sdio_bus, 0, sizeof(struct SdioBus));
|
||||
memset(&sdio_drv, 0, sizeof(struct SdioDriver));
|
||||
memset(&sdio_dev, 0, sizeof(struct SdioHardwareDevice));
|
||||
|
||||
SdCardConfig();
|
||||
|
||||
ret = SdioBusInit(&sdio_bus, SDIO_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("Sdio bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SdioDriverInit(&sdio_drv, SDIO_DRIVER_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("Sdio driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = SdioDriverAttachToBus(SDIO_DRIVER_NAME, SDIO_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("Sdio driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
sdio_dev.dev_done = &dev_done;
|
||||
sdio_dev.haldev.dev_block_control = SdioControl;
|
||||
ret = SdioDeviceRegister(&sdio_dev, SDIO_DEVICE_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("Sdio device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = SdioDeviceAttachToBus(SDIO_DEVICE_NAME, SDIO_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("Sdio device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
if BSP_USING_SPI
|
||||
config BSP_USING_SPI1
|
||||
bool "Using spi1"
|
||||
default y
|
||||
|
||||
if BSP_USING_SPI1
|
||||
config SPI_BUS_NAME_1
|
||||
string "spi bus 1 name"
|
||||
default "spi1"
|
||||
config SPI_1_DEVICE_NAME_0
|
||||
string "spi bus 1 device 0 name"
|
||||
default "spi1_dev0"
|
||||
config SPI_1_DRV_NAME
|
||||
string "spi bus 1 driver name"
|
||||
default "spi1_drv"
|
||||
|
||||
menuconfig RESOURCES_SPI_LORA
|
||||
bool "Using spi lora function"
|
||||
default n
|
||||
if RESOURCES_SPI_LORA
|
||||
config SX12XX_DEVICE_NAME
|
||||
string "SX12XX(SX1278 SX1276) lora device name"
|
||||
default "spi1_lora"
|
||||
endif
|
||||
endif
|
||||
|
||||
config BSP_USING_SPI6
|
||||
bool "Using spi6"
|
||||
default n
|
||||
|
||||
if BSP_USING_SPI6
|
||||
config SPI_BUS_NAME_6
|
||||
string "spi bus 6 name"
|
||||
default "spi6"
|
||||
config SPI_6_DEVICE_NAME_0
|
||||
string "spi bus 6 device 0 name"
|
||||
default "spi6_dev0"
|
||||
config SPI_6_DRV_NAME
|
||||
string "spi bus 6 driver name"
|
||||
default "spi6_drv"
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,8 @@
|
||||
SRC_FILES := connect_spi.c
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_SPI_LORA),y)
|
||||
SRC_DIR := third_party_spi_lora
|
||||
SRC_FILES += connect_lora_spi.c
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_lora_spi.c
|
||||
* @brief support to register spi lora pointer and function
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-31
|
||||
*/
|
||||
|
||||
#include <connect_spi_lora.h>
|
||||
|
||||
/* RST = PI02 */
|
||||
#define LORA_RST_PORT (GPIO_PORT_I)
|
||||
#define LORA_RST_PIN (GPIO_PIN_02)
|
||||
|
||||
static struct HardwareDev *g_spi_lora_dev;
|
||||
tRadioDriver *Radio = NONE;
|
||||
|
||||
void SX1276InitIo(void)
|
||||
{
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinState = PIN_STAT_RST;
|
||||
stcGpioInit.u16PinDir = PIN_DIR_OUT;
|
||||
(void)GPIO_Init(LORA_RST_PORT, LORA_RST_PIN, &stcGpioInit);
|
||||
}
|
||||
|
||||
inline void SX1276WriteRxTx(uint8_t txEnable)
|
||||
{
|
||||
if (txEnable != 0) {
|
||||
/*to do*/
|
||||
} else {
|
||||
/*to do*/
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276SetReset(uint8_t state)
|
||||
{
|
||||
if (state == RADIO_RESET_ON) {
|
||||
GPIO_ResetPins(LORA_RST_PORT, LORA_RST_PIN);
|
||||
} else {
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinDir = PIN_DIR_IN;
|
||||
(void)GPIO_Init(LORA_RST_PORT, LORA_RST_PIN, &stcGpioInit);
|
||||
}
|
||||
}
|
||||
|
||||
//Not-necessary Function
|
||||
uint8_t SX1276ReadDio0(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t SX1276ReadDio1(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t SX1276ReadDio2(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t SX1276ReadDio3(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t SX1276ReadDio4(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t SX1276ReadDio5(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SX1276WriteBuffer(uint8_t addr, uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
struct BusBlockWriteParam write_param;
|
||||
uint8 write_addr = addr | 0x80;
|
||||
|
||||
BusDevOpen(g_spi_lora_dev);
|
||||
|
||||
write_param.buffer = (void *)&write_addr;
|
||||
write_param.size = 1;
|
||||
BusDevWriteData(g_spi_lora_dev, &write_param);
|
||||
|
||||
write_param.buffer = (void *)buffer;
|
||||
write_param.size = size;
|
||||
BusDevWriteData(g_spi_lora_dev, &write_param);
|
||||
|
||||
BusDevClose(g_spi_lora_dev);
|
||||
}
|
||||
|
||||
void SX1276ReadBuffer(uint8_t addr, uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
struct BusBlockWriteParam write_param;
|
||||
struct BusBlockReadParam read_param;
|
||||
|
||||
uint8 write_addr = addr & 0x7F;
|
||||
|
||||
BusDevOpen(g_spi_lora_dev);
|
||||
|
||||
write_param.buffer = (void *)&write_addr;
|
||||
write_param.size = 1;
|
||||
BusDevWriteData(g_spi_lora_dev, &write_param);
|
||||
|
||||
read_param.buffer = (void *)buffer;
|
||||
read_param.size = size;
|
||||
BusDevReadData(g_spi_lora_dev, &read_param);
|
||||
|
||||
BusDevClose(g_spi_lora_dev);
|
||||
}
|
||||
|
||||
void SX1276WriteFifo(uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
SX1276WriteBuffer(0, buffer, size);
|
||||
}
|
||||
|
||||
void SX1276ReadFifo(uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
SX1276ReadBuffer(0, buffer, size);
|
||||
}
|
||||
|
||||
void SX1276Write(uint8_t addr, uint8_t data)
|
||||
{
|
||||
SX1276WriteBuffer(addr, &data, 1);
|
||||
}
|
||||
|
||||
void SX1276Read(uint8_t addr, uint8_t *data)
|
||||
{
|
||||
SX1276ReadBuffer(addr, data, 1);
|
||||
}
|
||||
|
||||
uint8_t Sx1276SpiCheck(void)
|
||||
{
|
||||
uint8_t test = 0;
|
||||
|
||||
tLoRaSettings settings;
|
||||
SX1276Read(REG_LR_VERSION, &test);
|
||||
KPrintf("version code of the chip is 0x%x\n", test);
|
||||
|
||||
settings.RFFrequency = SX1276LoRaGetRFFrequency();
|
||||
KPrintf("SX1278 Lora parameters are :\nRFFrequency is %d\n", settings.RFFrequency);
|
||||
|
||||
settings.Power = SX1276LoRaGetRFPower();
|
||||
KPrintf("RFPower is %d\n",settings.Power);
|
||||
|
||||
settings.SignalBw = SX1276LoRaGetSignalBandwidth();
|
||||
KPrintf("SignalBw is %d\n",settings.SignalBw);
|
||||
|
||||
settings.SpreadingFactor = SX1276LoRaGetSpreadingFactor();
|
||||
KPrintf("SpreadingFactor is %d\n",settings.SpreadingFactor);
|
||||
|
||||
/*SPI confirm*/
|
||||
SX1276Write(REG_LR_HOPPERIOD, 0x91);
|
||||
SX1276Read(REG_LR_HOPPERIOD, &test);
|
||||
if (test != 0x91) {
|
||||
return 0;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function supports to write data to the lora.
|
||||
*
|
||||
* @param dev lora dev descriptor
|
||||
* @param write_param lora dev write datacfg param
|
||||
*/
|
||||
static uint32 SpiLoraWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
NULL_PARAM_CHECK(write_param);
|
||||
|
||||
if (write_param->size > 256) {
|
||||
KPrintf("SpiLoraWrite ERROR:The message is too long!\n");
|
||||
return ERROR;
|
||||
} else {
|
||||
SX1276SetTxPacket(write_param->buffer, write_param->size);
|
||||
while(SX1276Process() != RF_TX_DONE);
|
||||
KPrintf("SpiLoraWrite success!\n");
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function supports to read data from the lora.
|
||||
*
|
||||
* @param dev lora dev descriptor
|
||||
* @param read_param lora dev read datacfg param
|
||||
*/
|
||||
static uint32 SpiLoraRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
NULL_PARAM_CHECK(read_param);
|
||||
|
||||
int read_times = 100;
|
||||
|
||||
SX1276StartRx();
|
||||
KPrintf("SpiLoraRead Ready!\n");
|
||||
|
||||
while (read_times) {
|
||||
if (SX1276Process() != RF_RX_DONE) {
|
||||
read_times --;
|
||||
MdelayKTask(500);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_times > 0) {
|
||||
SX1276GetRxPacket(read_param->buffer, (uint16 *)&read_param->read_length);
|
||||
} else {
|
||||
read_param->read_length = 0;
|
||||
}
|
||||
|
||||
return read_param->read_length;
|
||||
}
|
||||
|
||||
static uint32 SpiLoraOpen(void *dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
KPrintf("SpiLoraOpen start\n");
|
||||
|
||||
x_err_t ret = EOK;
|
||||
static x_bool lora_init_status = RET_FALSE;
|
||||
|
||||
if (RET_TRUE == lora_init_status) {
|
||||
return EOK;
|
||||
}
|
||||
|
||||
struct HardwareDev *haldev = (struct HardwareDev *)dev;
|
||||
|
||||
struct SpiHardwareDevice *lora_dev = CONTAINER_OF(haldev, struct SpiHardwareDevice, haldev);
|
||||
NULL_PARAM_CHECK(lora_dev);
|
||||
|
||||
SpiLoraDeviceType spi_lora_dev = CONTAINER_OF(lora_dev, struct SpiLoraDevice, lora_dev);
|
||||
NULL_PARAM_CHECK(spi_lora_dev);
|
||||
|
||||
struct Driver *spi_drv = spi_lora_dev->spi_dev->haldev.owner_bus->owner_driver;
|
||||
|
||||
struct BusConfigureInfo configure_info;
|
||||
struct SpiMasterParam spi_master_param;
|
||||
spi_master_param.spi_data_bit_width = 8;
|
||||
spi_master_param.spi_work_mode = SPI_MODE_0 | SPI_MSB;
|
||||
|
||||
configure_info.configure_cmd = OPE_CFG;
|
||||
configure_info.private_data = (void *)&spi_master_param;
|
||||
ret = BusDrvConfigure(spi_drv, &configure_info);
|
||||
if (ret) {
|
||||
KPrintf("spi drv OPE_CFG error drv %8p cfg %8p\n", spi_drv, &spi_master_param);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
configure_info.configure_cmd = OPE_INT;
|
||||
ret = BusDrvConfigure(spi_drv, &configure_info);
|
||||
if (ret) {
|
||||
KPrintf("spi drv OPE_INT error drv %8p\n", spi_drv);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
SX1276Init();
|
||||
|
||||
if (0x91 != Sx1276SpiCheck()) {
|
||||
KPrintf("LoRa check failed!\n!");
|
||||
} else {
|
||||
Radio = RadioDriverInit();
|
||||
KPrintf("LoRa check ok!\nNote: The length of the message that can be sent in a single time is 256 characters\n");
|
||||
}
|
||||
|
||||
lora_init_status = RET_TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32 SpiLoraClose(void *dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static const struct LoraDevDone lora_done =
|
||||
{
|
||||
.open = SpiLoraOpen,
|
||||
.close = SpiLoraClose,
|
||||
.write = SpiLoraWrite,
|
||||
.read = SpiLoraRead,
|
||||
};
|
||||
|
||||
/**
|
||||
* This function supports to init spi_lora_dev
|
||||
*
|
||||
* @param bus_name spi bus name
|
||||
* @param dev_name spi dev name
|
||||
* @param drv_name spi drv name
|
||||
* @param lora_name lora dev name
|
||||
*/
|
||||
SpiLoraDeviceType SpiLoraInit(char *bus_name, char *dev_name, char *drv_name, char *lora_name)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev_name);
|
||||
NULL_PARAM_CHECK(drv_name);
|
||||
NULL_PARAM_CHECK(lora_name);
|
||||
NULL_PARAM_CHECK(bus_name);
|
||||
|
||||
x_err_t ret;
|
||||
static HardwareDevType haldev;
|
||||
|
||||
haldev = SpiDeviceFind(dev_name, TYPE_SPI_DEV);
|
||||
if (NONE == haldev) {
|
||||
KPrintf("SpiLoraInit find spi haldev %s error! \n", dev_name);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
SpiLoraDeviceType spi_lora_dev = (SpiLoraDeviceType)malloc(sizeof(struct SpiLoraDevice));
|
||||
if (NONE == spi_lora_dev) {
|
||||
KPrintf("SpiLoraInit malloc spi_lora_dev failed\n");
|
||||
free(spi_lora_dev);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
memset(spi_lora_dev, 0, sizeof(struct SpiLoraDevice));
|
||||
|
||||
spi_lora_dev->spi_dev = CONTAINER_OF(haldev, struct SpiHardwareDevice, haldev);
|
||||
|
||||
spi_lora_dev->lora_dev.spi_dev_flag = RET_TRUE;
|
||||
spi_lora_dev->lora_dev.haldev.dev_done = (struct HalDevDone *)&lora_done;
|
||||
|
||||
struct Driver *spi_driver = SpiDriverFind(drv_name, TYPE_SPI_DRV);
|
||||
if (NONE == spi_driver) {
|
||||
KPrintf("SpiLoraInit find spi driver %s error! \n", drv_name);
|
||||
free(spi_lora_dev);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
//spi drv get spi dev param (SpiDeviceParam)
|
||||
spi_driver->private_data = spi_lora_dev->spi_dev->haldev.private_data;
|
||||
spi_lora_dev->spi_dev->haldev.owner_bus->owner_driver = spi_driver;
|
||||
|
||||
ret = SpiDeviceRegister(&spi_lora_dev->lora_dev, spi_lora_dev->spi_dev->haldev.private_data, lora_name);
|
||||
if (EOK != ret) {
|
||||
KPrintf("SpiLoraInit SpiDeviceRegister device %s error %d\n", lora_name, ret);
|
||||
free(spi_lora_dev);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(lora_name, bus_name);
|
||||
if (EOK != ret) {
|
||||
KPrintf("SpiLoraInit SpiDeviceAttachToBus device %s error %d\n", lora_name, ret);
|
||||
free(spi_lora_dev);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
g_spi_lora_dev = &spi_lora_dev->spi_dev->haldev;
|
||||
|
||||
return spi_lora_dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function supports to release spi_lora_dev
|
||||
*
|
||||
* @param spi_lora_dev spi lora descriptor
|
||||
*/
|
||||
uint32 SpiLoraRelease(SpiLoraDeviceType spi_lora_dev)
|
||||
{
|
||||
NULL_PARAM_CHECK(spi_lora_dev);
|
||||
|
||||
x_err_t ret;
|
||||
|
||||
DeviceDeleteFromBus(spi_lora_dev->lora_dev.haldev.owner_bus, &spi_lora_dev->lora_dev.haldev);
|
||||
|
||||
free(spi_lora_dev);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
int LoraSx12xxSpiDeviceInit(void)
|
||||
{
|
||||
#ifdef BSP_USING_SPI1
|
||||
if (NONE == SpiLoraInit(SPI_BUS_NAME_1, SPI_1_DEVICE_NAME_0, SPI_1_DRV_NAME, SX12XX_DEVICE_NAME)) {
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
#define LORA_TEST
|
||||
#ifdef LORA_TEST
|
||||
/*Just for lora test*/
|
||||
static struct Bus *bus;
|
||||
static struct HardwareDev *dev;
|
||||
|
||||
void LoraOpen(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
bus = BusFind(SPI_BUS_NAME_1);
|
||||
dev = BusFindDevice(bus, SX12XX_DEVICE_NAME);
|
||||
|
||||
ret = SpiLoraOpen(dev);
|
||||
if (EOK != ret) {
|
||||
KPrintf("LoRa init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
KPrintf("LoRa init succeed\n");
|
||||
|
||||
return;
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
LoraOpen, LoraOpen, open lora device and read parameters );
|
||||
|
||||
static void LoraReceive(void)
|
||||
{
|
||||
uint32 read_length = 0;
|
||||
struct BusBlockReadParam read_param;
|
||||
memset(&read_param, 0, sizeof(struct BusBlockReadParam));
|
||||
|
||||
read_param.buffer = malloc(SPI_LORA_BUFFER_SIZE);
|
||||
|
||||
read_length = SpiLoraRead(dev, &read_param);
|
||||
|
||||
KPrintf("LoraReceive length %d\n", read_length);
|
||||
for (int i = 0; i < read_length; i ++) {
|
||||
KPrintf("i %d data 0x%x\n", i, ((uint8 *)read_param.buffer)[i]);
|
||||
}
|
||||
|
||||
free(read_param.buffer);
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
|
||||
LoraReceive, LoraReceive, lora wait message );
|
||||
|
||||
static void LoraSend(int argc, char *argv[])
|
||||
{
|
||||
char Msg[SPI_LORA_BUFFER_SIZE] = {0};
|
||||
struct BusBlockWriteParam write_param;
|
||||
memset(&write_param, 0, sizeof(struct BusBlockWriteParam));
|
||||
|
||||
if (argc == 2) {
|
||||
strncpy(Msg, argv[1], SPI_LORA_BUFFER_SIZE);
|
||||
write_param.buffer = Msg;
|
||||
write_param.size = strlen(Msg);
|
||||
|
||||
KPrintf("LoraSend data %s length %d\n", Msg, strlen(Msg));
|
||||
|
||||
SpiLoraWrite(dev, &write_param);
|
||||
}
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
LoraSend, LoraSend, lora send message );
|
||||
#endif
|
||||
@@ -0,0 +1,585 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_spi.c
|
||||
* @brief support hc32f4a0-board spi function and register to bus framework
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-17
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: connect_spi.c
|
||||
Description: support hc32f4a0-board spi function and register to bus framework
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-10-17
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support hc32f4a0-board spi configure, write and read
|
||||
2. support hc32f4a0-board spi bus device and driver register
|
||||
3. SPI1 for LoRa, SPI6 using J12-pin-header to connect
|
||||
*************************************************/
|
||||
|
||||
#include <connect_spi.h>
|
||||
|
||||
#define SPI1_MASTER_SLAVE_MODE (SPI_MASTER)
|
||||
|
||||
/* SPI1 definition */
|
||||
#define SPI1_UNIT (CM_SPI1)
|
||||
#define SPI1_CLK (FCG1_PERIPH_SPI1)
|
||||
|
||||
/* SS = PI01 */
|
||||
#define SPI1_SS_PORT (GPIO_PORT_I)
|
||||
#define SPI1_SS_PIN (GPIO_PIN_01)
|
||||
/* SCK = PH14 */
|
||||
#define SPI1_SCK_PORT (GPIO_PORT_H)
|
||||
#define SPI1_SCK_PIN (GPIO_PIN_14)
|
||||
#define SPI1_SCK_FUNC (GPIO_FUNC_40)
|
||||
/* MOSI = PI00 */
|
||||
#define SPI1_MOSI_PORT (GPIO_PORT_I)
|
||||
#define SPI1_MOSI_PIN (GPIO_PIN_00)
|
||||
#define SPI1_MOSI_FUNC (GPIO_FUNC_41)
|
||||
/* MISO = PH15 */
|
||||
#define SPI1_MISO_PORT (GPIO_PORT_H)
|
||||
#define SPI1_MISO_PIN (GPIO_PIN_15)
|
||||
#define SPI1_MISO_FUNC (GPIO_FUNC_42)
|
||||
|
||||
#define SPI1_DEVICE_SLAVE_ID_0 0
|
||||
|
||||
/* SPI6 definition */
|
||||
#define SPI6_UNIT (CM_SPI6)
|
||||
#define SPI6_CLK (FCG1_PERIPH_SPI6)
|
||||
|
||||
/* SS = PI01 */
|
||||
#define SPI6_SS_PORT (GPIO_PORT_I)
|
||||
#define SPI6_SS_PIN (GPIO_PIN_01)
|
||||
/* SCK = PH14 */
|
||||
#define SPI6_SCK_PORT (GPIO_PORT_H)
|
||||
#define SPI6_SCK_PIN (GPIO_PIN_14)
|
||||
#define SPI6_SCK_FUNC (GPIO_FUNC_40)
|
||||
/* MOSI = PI00 */
|
||||
#define SPI6_MOSI_PORT (GPIO_PORT_I)
|
||||
#define SPI6_MOSI_PIN (GPIO_PIN_00)
|
||||
#define SPI6_MOSI_FUNC (GPIO_FUNC_41)
|
||||
/* MISO = PH15 */
|
||||
#define SPI6_MISO_PORT (GPIO_PORT_H)
|
||||
#define SPI6_MISO_PIN (GPIO_PIN_15)
|
||||
#define SPI6_MISO_FUNC (GPIO_FUNC_42)
|
||||
|
||||
#define SPI6_DEVICE_SLAVE_ID_0 0
|
||||
|
||||
static void HwSpiEnable(CM_SPI_TypeDef *SPIx)
|
||||
{
|
||||
/* Check if the SPI is already enabled */
|
||||
if (SPI_CR1_SPE != (SPIx->CR1 & SPI_CR1_SPE)) {
|
||||
SPI_Cmd(SPIx, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*Init the spi sdk intetface */
|
||||
static uint32 SpiSdkInit(struct SpiDriver *spi_drv)
|
||||
{
|
||||
NULL_PARAM_CHECK(spi_drv);
|
||||
|
||||
stc_spi_init_t stcSpiInit;
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
|
||||
|
||||
#ifdef BSP_USING_SPI1
|
||||
/* Configure Port */
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinState = PIN_STAT_RST;
|
||||
stcGpioInit.u16PinDir = PIN_DIR_OUT;
|
||||
(void)GPIO_Init(SPI1_SS_PORT, SPI1_SS_PIN, &stcGpioInit);
|
||||
GPIO_SetPins(SPI1_SS_PORT, SPI1_SS_PIN);
|
||||
|
||||
GPIO_SetFunc(SPI1_SCK_PORT, SPI1_SCK_PIN, SPI1_SCK_FUNC);
|
||||
GPIO_SetFunc(SPI1_MOSI_PORT, SPI1_MOSI_PIN, SPI1_MOSI_FUNC);
|
||||
GPIO_SetFunc(SPI1_MISO_PORT, SPI1_MISO_PIN, SPI1_MISO_FUNC);
|
||||
|
||||
/* Configuration SPI */
|
||||
FCG_Fcg1PeriphClockCmd(SPI1_CLK, ENABLE);
|
||||
SPI_StructInit(&stcSpiInit);
|
||||
|
||||
stcSpiInit.u32WireMode = SPI_4_WIRE;
|
||||
stcSpiInit.u32TransMode = SPI_FULL_DUPLEX;
|
||||
stcSpiInit.u32MasterSlave = SPI1_MASTER_SLAVE_MODE;
|
||||
stcSpiInit.u32Parity = SPI_PARITY_INVD;
|
||||
|
||||
if (SPI_MODE_0 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_0;
|
||||
} else if (SPI_MODE_1 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_1;
|
||||
} else if (SPI_MODE_2 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_2;
|
||||
} else if (SPI_MODE_3 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_3;
|
||||
}
|
||||
|
||||
stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV64;
|
||||
|
||||
if (8 == dev_param->spi_master_param->spi_data_bit_width) {
|
||||
stcSpiInit.u32DataBits = SPI_DATA_SIZE_8BIT;
|
||||
} else if (7 == dev_param->spi_master_param->spi_data_bit_width) {
|
||||
stcSpiInit.u32DataBits = SPI_DATA_SIZE_7BIT;
|
||||
}
|
||||
|
||||
if (SPI_LSB == dev_param->spi_master_param->spi_work_mode & 0x4) {
|
||||
stcSpiInit.u32FirstBit = SPI_FIRST_LSB;
|
||||
} else if(SPI_MSB == dev_param->spi_master_param->spi_work_mode & 0x4) {
|
||||
stcSpiInit.u32FirstBit = SPI_FIRST_MSB;
|
||||
}
|
||||
|
||||
stcSpiInit.u32FrameLevel = SPI_1_FRAME;
|
||||
|
||||
(void)SPI_Init(SPI1_UNIT, &stcSpiInit);
|
||||
SPI_Cmd(SPI1_UNIT, ENABLE);
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SPI6
|
||||
/* Configure Port */
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinState = PIN_STAT_RST;
|
||||
stcGpioInit.u16PinDir = PIN_DIR_OUT;
|
||||
(void)GPIO_Init(SPI6_SS_PORT, SPI6_SS_PIN, &stcGpioInit);
|
||||
GPIO_SetPins(SPI6_SS_PORT, SPI6_SS_PIN);
|
||||
|
||||
GPIO_SetFunc(SPI6_SCK_PORT, SPI6_SCK_PIN, SPI6_SCK_FUNC);
|
||||
GPIO_SetFunc(SPI6_MOSI_PORT, SPI6_MOSI_PIN, SPI6_MOSI_FUNC);
|
||||
GPIO_SetFunc(SPI6_MISO_PORT, SPI6_MISO_PIN, SPI6_MISO_FUNC);
|
||||
|
||||
/* Configuration SPI */
|
||||
FCG_Fcg1PeriphClockCmd(SPI6_CLK, ENABLE);
|
||||
SPI_StructInit(&stcSpiInit);
|
||||
|
||||
stcSpiInit.u32WireMode = SPI_4_WIRE;
|
||||
stcSpiInit.u32TransMode = SPI_FULL_DUPLEX;
|
||||
stcSpiInit.u32MasterSlave = SPI1_MASTER_SLAVE_MODE;
|
||||
stcSpiInit.u32Parity = SPI_PARITY_INVD;
|
||||
|
||||
if (SPI_MODE_0 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_0;
|
||||
} else if (SPI_MODE_1 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_1;
|
||||
} else if (SPI_MODE_2 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_2;
|
||||
} else if (SPI_MODE_3 == dev_param->spi_master_param->spi_work_mode & 0x3) {
|
||||
stcSpiInit.u32SpiMode = SPI_MD_3;
|
||||
}
|
||||
|
||||
stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV64;
|
||||
|
||||
if (8 == dev_param->spi_master_param->spi_data_bit_width) {
|
||||
stcSpiInit.u32DataBits = SPI_DATA_SIZE_8BIT;
|
||||
} else if (7 == dev_param->spi_master_param->spi_data_bit_width) {
|
||||
stcSpiInit.u32DataBits = SPI_DATA_SIZE_7BIT;
|
||||
}
|
||||
|
||||
if (SPI_LSB == dev_param->spi_master_param->spi_work_mode & 0x4) {
|
||||
stcSpiInit.u32FirstBit = SPI_FIRST_LSB;
|
||||
} else if(SPI_MSB == dev_param->spi_master_param->spi_work_mode & 0x4) {
|
||||
stcSpiInit.u32FirstBit = SPI_FIRST_MSB;
|
||||
}
|
||||
|
||||
stcSpiInit.u32FrameLevel = SPI_1_FRAME;
|
||||
|
||||
(void)SPI_Init(SPI6_UNIT, &stcSpiInit);
|
||||
SPI_Cmd(SPI6_UNIT, ENABLE);
|
||||
#endif
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 SpiSdkCfg(struct SpiDriver *spi_drv, struct SpiMasterParam *spi_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(spi_drv);
|
||||
NULL_PARAM_CHECK(spi_param);
|
||||
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_drv->driver.private_data);
|
||||
|
||||
dev_param->spi_master_param = spi_param;
|
||||
dev_param->spi_master_param->spi_work_mode = dev_param->spi_master_param->spi_work_mode & SPI_MODE_MASK;
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*Configure the spi device param, make sure struct (configure_info->private_data) = (SpiMasterParam)*/
|
||||
static uint32 SpiDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
NULL_PARAM_CHECK(configure_info);
|
||||
|
||||
x_err_t ret = EOK;
|
||||
struct SpiDriver *spi_drv = (struct SpiDriver *)drv;
|
||||
struct SpiMasterParam *spi_param;
|
||||
|
||||
switch (configure_info->configure_cmd)
|
||||
{
|
||||
case OPE_INT:
|
||||
ret = SpiSdkInit(spi_drv);
|
||||
break;
|
||||
case OPE_CFG:
|
||||
spi_param = (struct SpiMasterParam *)configure_info->private_data;
|
||||
ret = SpiSdkCfg(spi_drv, spi_param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32 SpiWriteData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
|
||||
{
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
|
||||
|
||||
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
uint8 cs_gpio_port = dev_param->spi_slave_param->spi_cs_gpio_port;
|
||||
CM_SPI_TypeDef *spi = spi_dev->haldev.owner_bus->private_data;
|
||||
|
||||
int i = 0;
|
||||
uint32 ret = EOK;
|
||||
int32 spi_write_status = 0;
|
||||
|
||||
while (NONE != spi_datacfg) {
|
||||
if (spi_datacfg->spi_chip_select) {
|
||||
GPIO_ResetPins(cs_gpio_port, cs_gpio_pin);
|
||||
}
|
||||
|
||||
if (spi_datacfg->length) {
|
||||
uint8 *tx_buff = x_malloc(spi_datacfg->length);
|
||||
if ((spi_datacfg->tx_buff) && (tx_buff)) {
|
||||
memset(tx_buff, 0, spi_datacfg->length);
|
||||
|
||||
for (i = 0; i < spi_datacfg->length; i++) {
|
||||
tx_buff[i] = ((uint8 *)spi_datacfg->tx_buff)[i];
|
||||
}
|
||||
|
||||
HwSpiEnable(spi);
|
||||
spi_write_status = SPI_Trans(spi, tx_buff, spi_datacfg->length, 1000);
|
||||
|
||||
while (RESET != SPI_GetStatus(spi, SPI_FLAG_IDLE));
|
||||
|
||||
if (LL_OK == spi_write_status) {
|
||||
ret = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_buff) {
|
||||
x_free(tx_buff);
|
||||
}
|
||||
|
||||
SPI_ClearStatus(spi, SPI_FLAG_CLR_ALL | SPI_FLAG_RX_BUF_FULL);
|
||||
}
|
||||
|
||||
if (spi_datacfg->spi_cs_release) {
|
||||
GPIO_SetPins(cs_gpio_port, cs_gpio_pin);
|
||||
}
|
||||
|
||||
spi_datacfg = spi_datacfg->next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32 SpiReadData(struct SpiHardwareDevice *spi_dev, struct SpiDataStandard *spi_datacfg)
|
||||
{
|
||||
SpiDeviceParam *dev_param = (SpiDeviceParam *)(spi_dev->haldev.private_data);
|
||||
|
||||
uint8 cs_gpio_pin = dev_param->spi_slave_param->spi_cs_gpio_pin;
|
||||
uint8 cs_gpio_port = dev_param->spi_slave_param->spi_cs_gpio_port;
|
||||
CM_SPI_TypeDef *spi = spi_dev->haldev.owner_bus->private_data;
|
||||
|
||||
int i = 0;
|
||||
int32 spi_read_status = 0;
|
||||
uint32 spi_read_length = 0;
|
||||
|
||||
while (NONE != spi_datacfg) {
|
||||
if (spi_datacfg->spi_chip_select) {
|
||||
GPIO_ResetPins(cs_gpio_port, cs_gpio_pin);
|
||||
}
|
||||
|
||||
if (spi_datacfg->length) {
|
||||
uint8_t *rx_buff = x_malloc(spi_datacfg->length);
|
||||
if ((spi_datacfg->rx_buff) && (rx_buff)) {
|
||||
memset(rx_buff, 0xFF, spi_datacfg->length);
|
||||
|
||||
HwSpiEnable(spi);
|
||||
spi_read_status = SPI_Receive(spi, rx_buff, spi_datacfg->length, 1000);
|
||||
|
||||
while (RESET != SPI_GetStatus(spi, SPI_FLAG_IDLE));
|
||||
if (LL_OK == spi_read_status) {
|
||||
for (i = 0; i < spi_datacfg->length; i++) {
|
||||
((uint8_t *)spi_datacfg->rx_buff)[i] = rx_buff[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rx_buff) {
|
||||
x_free(rx_buff);
|
||||
}
|
||||
|
||||
SPI_ClearStatus(spi, SPI_FLAG_CLR_ALL | SPI_FLAG_RX_BUF_FULL);
|
||||
}
|
||||
|
||||
if (spi_datacfg->spi_cs_release) {
|
||||
GPIO_SetPins(cs_gpio_port, cs_gpio_pin);
|
||||
}
|
||||
|
||||
spi_read_length += spi_datacfg->length;
|
||||
spi_datacfg = spi_datacfg->next;
|
||||
}
|
||||
|
||||
return spi_read_length;
|
||||
}
|
||||
|
||||
/*manage the spi device operations*/
|
||||
static const struct SpiDevDone spi_dev_done =
|
||||
{
|
||||
.dev_open = NONE,
|
||||
.dev_close = NONE,
|
||||
.dev_write = SpiWriteData,
|
||||
.dev_read = SpiReadData,
|
||||
};
|
||||
|
||||
static int BoardSpiBusInit(struct SpiBus *spi_bus, struct SpiDriver *spi_driver, const char *bus_name, const char *drv_name)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
/*Init the spi bus */
|
||||
ret = SpiBusInit(spi_bus, bus_name);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiBusInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Init the spi driver*/
|
||||
ret = SpiDriverInit(spi_driver, drv_name);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDriverInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Attach the spi driver to the spi bus*/
|
||||
ret = SpiDriverAttachToBus(drv_name, bus_name);
|
||||
if (EOK != ret) {
|
||||
KPrintf("Board_Spi_init SpiDriverAttachToBus error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Attach the spi device to the spi bus*/
|
||||
static int BoardSpiDevBend(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
#ifdef SPI_1_DEVICE_NAME_0
|
||||
static struct SpiHardwareDevice spi1_device0;
|
||||
memset(&spi1_device0, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
static struct SpiSlaveParam spi1_slaveparam0;
|
||||
memset(&spi1_slaveparam0, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi1_slaveparam0.spi_slave_id = SPI1_DEVICE_SLAVE_ID_0;
|
||||
spi1_slaveparam0.spi_cs_gpio_pin = SPI1_SS_PIN;
|
||||
spi1_slaveparam0.spi_cs_gpio_port = SPI1_SS_PORT;
|
||||
|
||||
spi1_device0.spi_param.spi_slave_param = &spi1_slaveparam0;
|
||||
|
||||
spi1_device0.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi1_device0, (void *)(&spi1_device0.spi_param), SPI_1_DEVICE_NAME_0);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend SpiDeviceRegister device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_1_DEVICE_NAME_0, SPI_BUS_NAME_1);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend SpiDeviceAttachToBus device %s error %d\n", SPI_1_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPI_6_DEVICE_NAME_0
|
||||
static struct SpiHardwareDevice spi6_device0;
|
||||
memset(&spi6_device0, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
static struct SpiSlaveParam spi6_slaveparam0;
|
||||
memset(&spi6_slaveparam0, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi6_slaveparam0.spi_slave_id = SPI1_DEVICE_SLAVE_ID_0;
|
||||
spi6_slaveparam0.spi_cs_gpio_pin = SPI6_SS_PIN;
|
||||
spi6_slaveparam0.spi_cs_gpio_port = SPI6_SS_PORT;
|
||||
|
||||
spi6_device0.spi_param.spi_slave_param = &spi6_slaveparam0;
|
||||
|
||||
spi6_device0.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
ret = SpiDeviceRegister(&spi6_device0, (void *)(&spi6_device0.spi_param), SPI_6_DEVICE_NAME_0);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend SpiDeviceRegister device %s error %d\n", SPI_6_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = SpiDeviceAttachToBus(SPI_6_DEVICE_NAME_0, SPI_BUS_NAME_6);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend SpiDeviceAttachToBus device %s error %d\n", SPI_6_DEVICE_NAME_0, ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int HwSpiInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
#ifdef BSP_USING_SPI1
|
||||
static struct SpiBus spi1_bus;
|
||||
memset(&spi1_bus, 0, sizeof(struct SpiBus));
|
||||
|
||||
static struct SpiDriver spi1_driver;
|
||||
memset(&spi1_driver, 0, sizeof(struct SpiDriver));
|
||||
|
||||
spi1_bus.private_data = SPI1_UNIT;
|
||||
spi1_driver.configure = SpiDrvConfigure;
|
||||
|
||||
ret = BoardSpiBusInit(&spi1_bus, &spi1_driver, SPI_BUS_NAME_1, SPI_1_DRV_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiBusInit error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardSpiDevBend();
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SPI6
|
||||
static struct SpiBus spi6_bus;
|
||||
memset(&spi6_bus, 0, sizeof(struct SpiBus));
|
||||
|
||||
static struct SpiDriver spi6_driver;
|
||||
memset(&spi6_driver, 0, sizeof(struct SpiDriver));
|
||||
|
||||
spi6_bus.private_data = SPI6_UNIT;
|
||||
spi6_driver.configure = SpiDrvConfigure;
|
||||
|
||||
ret = BoardSpiBusInit(&spi6_bus, &spi6_driver, SPI_BUS_NAME_6, SPI_6_DRV_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiBusInit error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardSpiDevBend();
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardSpiDevBend error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Just for lora test*/
|
||||
static struct Bus *bus;
|
||||
static struct HardwareDev *dev;
|
||||
static struct Driver *drv;
|
||||
|
||||
static uint32 TestSpiLoraOpen(void)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
|
||||
KPrintf("SpiLoraOpen start\n");
|
||||
|
||||
x_err_t ret = EOK;
|
||||
|
||||
struct BusConfigureInfo configure_info;
|
||||
struct SpiMasterParam spi_master_param;
|
||||
spi_master_param.spi_data_bit_width = 8;
|
||||
spi_master_param.spi_work_mode = SPI_MODE_0 | SPI_MSB;
|
||||
|
||||
configure_info.configure_cmd = OPE_CFG;
|
||||
configure_info.private_data = (void *)&spi_master_param;
|
||||
ret = BusDrvConfigure(drv, &configure_info);
|
||||
if (ret) {
|
||||
KPrintf("spi drv OPE_CFG error drv %8p cfg %8p\n", drv, &spi_master_param);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
configure_info.configure_cmd = OPE_INT;
|
||||
ret = BusDrvConfigure(drv, &configure_info);
|
||||
if (ret) {
|
||||
KPrintf("spi drv OPE_INT error drv %8p\n", drv);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void TestSpiRead(void)
|
||||
{
|
||||
struct BusBlockWriteParam write_param;
|
||||
struct BusBlockReadParam read_param;
|
||||
|
||||
uint8 write_addr = 0x06 & 0x7F;
|
||||
uint8 read_data = 0;
|
||||
|
||||
BusDevOpen(dev);
|
||||
|
||||
write_param.buffer = (void *)&write_addr;
|
||||
write_param.size = 1;
|
||||
BusDevWriteData(dev, &write_param);
|
||||
|
||||
read_param.buffer = (void *)&read_data;
|
||||
read_param.size = 1;
|
||||
BusDevReadData(dev, &read_param);
|
||||
|
||||
BusDevClose(dev);
|
||||
|
||||
KPrintf("read data from lora 0x06 register, receive data 0x%x\n", read_data);
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
TestSpiRead, TestSpiRead, read data from lora register);
|
||||
|
||||
void TestLoraOpen(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
bus = BusFind(SPI_BUS_NAME_1);
|
||||
dev = BusFindDevice(bus, SPI_1_DEVICE_NAME_0);
|
||||
drv = BusFindDriver(bus, SPI_1_DRV_NAME);
|
||||
|
||||
bus->match(drv, dev);
|
||||
|
||||
ret = TestSpiLoraOpen();
|
||||
if (EOK != ret) {
|
||||
KPrintf("LoRa init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
KPrintf("LoRa init succeed\n");
|
||||
|
||||
return;
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
TestLoraOpen, TestLoraOpen, open lora device and read parameters);
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ifeq ($(CONFIG_RESOURCES_SPI_LORA),y)
|
||||
SRC_DIR := sx12xx
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := src
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file spi_lora_sx12xx.h
|
||||
* @brief define spi lora driver function
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-31
|
||||
*/
|
||||
|
||||
#ifndef SPI_LORA_SX12XX_H
|
||||
#define SPI_LORA_SX12XX_H
|
||||
|
||||
#include <connect_spi_lora.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint8_t SX1276ReadDio0(void);
|
||||
uint8_t SX1276ReadDio1(void);
|
||||
uint8_t SX1276ReadDio2(void);
|
||||
uint8_t SX1276ReadDio3(void);
|
||||
uint8_t SX1276ReadDio4(void);
|
||||
uint8_t SX1276ReadDio5(void);
|
||||
|
||||
void SX1276Write(uint8_t addr, uint8_t data);
|
||||
void SX1276Read(uint8_t addr, uint8_t *data);
|
||||
void SX1276WriteBuffer(uint8_t addr, uint8_t *buffer, uint8_t size);
|
||||
void SX1276ReadBuffer(uint8_t addr, uint8_t *buffer, uint8_t size);
|
||||
void SX1276WriteFifo(uint8_t *buffer, uint8_t size);
|
||||
void SX1276ReadFifo(uint8_t *buffer, uint8_t size);
|
||||
void SX1276SetReset(uint8_t state);
|
||||
uint8_t Sx1276SpiCheck(void);
|
||||
void SX1276WriteRxTx(uint8_t txEnable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := radio
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := radio.c sx1276-Fsk.c sx1276-FskMisc.c sx1276-LoRa.c sx1276-LoRaMisc.c sx1276.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file platform.h
|
||||
* \brief
|
||||
*
|
||||
* \version 1.0
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*/
|
||||
/*************************************************
|
||||
File name: platform.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
#ifndef __PLATFORM_H__
|
||||
#define __PLATFORM_H__
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Platform definition
|
||||
*/
|
||||
#define Bleeper 3
|
||||
#define SX1243ska 2
|
||||
#define SX12xxEiger 1
|
||||
#define SX12000DVK 0
|
||||
|
||||
/*!
|
||||
* Platform choice. Please uncoment the PLATFORM define and choose your platform
|
||||
* or add/change the PLATFORM definition on the compiler Defines option
|
||||
*/
|
||||
#define PLATFORM SX12xxEiger
|
||||
|
||||
#if( PLATFORM == SX12xxEiger )
|
||||
/*!
|
||||
* Radio choice. Please uncomment the wanted radio and comment the others
|
||||
* or add/change wanted radio definition on the compiler Defines option
|
||||
*/
|
||||
//#define USE_SX1232_RADIO
|
||||
//#define USE_SX1272_RADIO
|
||||
#define USE_SX1276_RADIO
|
||||
//#define USE_SX1243_RADIO
|
||||
|
||||
/*!
|
||||
* Module choice. There are three existing module with the SX1276.
|
||||
* Please set the connected module to the value 1 and set the others to 0
|
||||
*/
|
||||
#ifdef USE_SX1276_RADIO
|
||||
#define MODULE_SX1276RF1IAS 0
|
||||
#define MODULE_SX1276RF1JAS 0
|
||||
#define MODULE_SX1276RF1KAS 1
|
||||
#endif
|
||||
|
||||
#include <spi_lora_sx12xx.h>
|
||||
#define USE_UART 0
|
||||
|
||||
#elif( PLATFORM == SX12000DVK )
|
||||
/*!
|
||||
* Radio choice. Please uncomment the wanted radio and comment the others
|
||||
* or add/change wanted radio definition on the compiler Defines option
|
||||
*/
|
||||
//#define USE_SX1232_RADIO
|
||||
#define USE_SX1272_RADIO
|
||||
//#define USE_SX1276_RADIO
|
||||
//#define USE_SX1243_RADIO
|
||||
|
||||
#include "sx1200dvk/sx1200dvk.h"
|
||||
|
||||
#elif( PLATFORM == SX1243ska )
|
||||
|
||||
#elif( PLATFORM == Bleeper )
|
||||
#define USE_SX1272_RADIO
|
||||
|
||||
#include "bleeper/bleeper.h"
|
||||
#define USE_UART 0
|
||||
|
||||
#else
|
||||
#error "Missing define: Platform (ie. SX12xxEiger)"
|
||||
#endif
|
||||
|
||||
#endif // __PLATFORM_H__
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file radio.c
|
||||
* \brief Generic radio driver ( radio abstraction )
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*
|
||||
* Last modified by Gregory Cristian on Apr 25 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: radio.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
#include "radio.h"
|
||||
|
||||
#if defined( USE_SX1232_RADIO )
|
||||
#include "sx1232.h"
|
||||
#elif defined( USE_SX1272_RADIO )
|
||||
#include "sx1272.h"
|
||||
#elif defined( USE_SX1276_RADIO )
|
||||
#include "sx1276.h"
|
||||
#else
|
||||
#error "Missing define: USE_XXXXXX_RADIO (ie. USE_SX1272_RADIO)"
|
||||
#endif
|
||||
|
||||
tRadioDriver RadioDriver;
|
||||
|
||||
tRadioDriver* RadioDriverInit( void )
|
||||
{
|
||||
#if defined( USE_SX1232_RADIO )
|
||||
RadioDriver.Init = SX1232Init;
|
||||
RadioDriver.Reset = SX1232Reset;
|
||||
RadioDriver.StartRx = SX1232StartRx;
|
||||
RadioDriver.GetRxPacket = SX1232GetRxPacket;
|
||||
RadioDriver.SetTxPacket = SX1232SetTxPacket;
|
||||
RadioDriver.Process = SX1232Process;
|
||||
#elif defined( USE_SX1272_RADIO )
|
||||
RadioDriver.Init = SX1272Init;
|
||||
RadioDriver.Reset = SX1272Reset;
|
||||
RadioDriver.StartRx = SX1272StartRx;
|
||||
RadioDriver.GetRxPacket = SX1272GetRxPacket;
|
||||
RadioDriver.SetTxPacket = SX1272SetTxPacket;
|
||||
RadioDriver.Process = SX1272Process;
|
||||
#elif defined( USE_SX1276_RADIO )
|
||||
RadioDriver.Init = SX1276Init;
|
||||
RadioDriver.Reset = SX1276Reset;
|
||||
RadioDriver.StartRx = SX1276StartRx;
|
||||
RadioDriver.GetRxPacket = SX1276GetRxPacket;
|
||||
RadioDriver.SetTxPacket = SX1276SetTxPacket;
|
||||
RadioDriver.Process = SX1276Process;
|
||||
RadioDriver.ChannelEmpty = SX1276ChannelEmpty;
|
||||
#else
|
||||
#error "Missing define: USE_XXXXXX_RADIO (ie. USE_SX1272_RADIO)"
|
||||
#endif
|
||||
|
||||
return &RadioDriver;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file radio.h
|
||||
* \brief Generic radio driver ( radio abstraction )
|
||||
*
|
||||
* \version 2.0.B2
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*
|
||||
* Last modified by Gregory Cristian on Apr 25 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: radio.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#ifndef __RADIO_H__
|
||||
#define __RADIO_H__
|
||||
|
||||
/*!
|
||||
* SX1272 and SX1276 General parameters definition
|
||||
*/
|
||||
#define LORA 1 // [0: OFF, 1: ON]
|
||||
|
||||
/*!
|
||||
* RF process function return codes
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
RF_IDLE,
|
||||
RF_BUSY,
|
||||
RF_RX_DONE,
|
||||
RF_RX_TIMEOUT,
|
||||
RF_TX_DONE,
|
||||
RF_TX_TIMEOUT,
|
||||
RF_LEN_ERROR,
|
||||
RF_CHANNEL_EMPTY,
|
||||
RF_CHANNEL_ACTIVITY_DETECTED,
|
||||
}tRFProcessReturnCodes;
|
||||
|
||||
/*!
|
||||
* Radio driver structure defining the different function pointers
|
||||
*/
|
||||
typedef struct sRadioDriver
|
||||
{
|
||||
void ( *Init )( void );
|
||||
void ( *Reset )( void );
|
||||
void ( *StartRx )( void );
|
||||
void ( *GetRxPacket )( void *buffer, uint16_t *size );
|
||||
void ( *SetTxPacket )( const void *buffer, uint16_t size );
|
||||
uint32_t ( *Process )( void );
|
||||
uint32_t ( *ChannelEmpty )(void );
|
||||
}tRadioDriver;
|
||||
|
||||
/*!
|
||||
* \brief Initializes the RadioDriver structure with specific radio
|
||||
* functions.
|
||||
*
|
||||
* \retval radioDriver Pointer to the radio driver variable
|
||||
*/
|
||||
tRadioDriver* RadioDriverInit( void );
|
||||
|
||||
#endif // __RADIO_H__
|
||||
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276.c
|
||||
* \brief SX1276 RF chip driver
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-Fsk.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if defined( USE_SX1276_RADIO )
|
||||
|
||||
#include "radio.h"
|
||||
|
||||
#include "sx1276-Hal.h"
|
||||
#include "sx1276.h"
|
||||
|
||||
#include "sx1276-FskMisc.h"
|
||||
#include "sx1276-Fsk.h"
|
||||
|
||||
// Default settings
|
||||
tFskSettings FskSettings =
|
||||
{
|
||||
870000000, // RFFrequency
|
||||
9600, // Bitrate
|
||||
50000, // Fdev
|
||||
20, // Power
|
||||
100000, // RxBw
|
||||
150000, // RxBwAfc
|
||||
true, // CrcOn
|
||||
true, // AfcOn
|
||||
255 // PayloadLength (set payload size to the maximum for variable mode, else set the exact payload length)
|
||||
};
|
||||
|
||||
/*!
|
||||
* SX1276 FSK registers variable
|
||||
*/
|
||||
tSX1276* SX1276;
|
||||
|
||||
/*!
|
||||
* Local RF buffer for communication support
|
||||
*/
|
||||
static uint8_t RFBuffer[RF_BUFFER_SIZE];
|
||||
|
||||
/*!
|
||||
* Chunk size of data write in buffer
|
||||
*/
|
||||
static uint8_t DataChunkSize = 32;
|
||||
|
||||
|
||||
/*!
|
||||
* RF state machine variable
|
||||
*/
|
||||
static uint8_t RFState = RF_STATE_IDLE;
|
||||
|
||||
/*!
|
||||
* Rx management support variables
|
||||
*/
|
||||
|
||||
/*!
|
||||
* PacketTimeout holds the RF packet timeout
|
||||
* SyncSize = [0..8]
|
||||
* VariableSize = [0;1]
|
||||
* AddressSize = [0;1]
|
||||
* PayloadSize = [0..RF_BUFFER_SIZE]
|
||||
* CrcSize = [0;2]
|
||||
* PacketTimeout = ( ( 8 * ( VariableSize + AddressSize + PayloadSize + CrcSize ) / BR ) * 1000.0 ) + 1
|
||||
* Computed timeout is in miliseconds
|
||||
*/
|
||||
static uint32_t PacketTimeout;
|
||||
|
||||
/*!
|
||||
* Preamble2SyncTimeout
|
||||
* Preamble2SyncTimeout = ( ( 8 * ( PremableSize + SyncSize ) / RFBitrate ) * 1000.0 ) + 1
|
||||
* Computed timeout is in miliseconds
|
||||
*/
|
||||
static uint32_t Preamble2SyncTimeout;
|
||||
|
||||
static bool PreambleDetected = false;
|
||||
static bool SyncWordDetected = false;
|
||||
static bool PacketDetected = false;
|
||||
static uint16_t RxPacketSize = 0;
|
||||
static uint8_t RxBytesRead = 0;
|
||||
static uint8_t TxBytesSent = 0;
|
||||
static double RxPacketRssiValue;
|
||||
static uint32_t RxPacketAfcValue;
|
||||
static uint8_t RxGain = 1;
|
||||
static uint32_t RxTimeoutTimer = 0;
|
||||
static uint32_t Preamble2SyncTimer = 0;
|
||||
|
||||
/*!
|
||||
* Tx management support variables
|
||||
*/
|
||||
static uint16_t TxPacketSize = 0;
|
||||
static uint32_t TxTimeoutTimer = 0;
|
||||
|
||||
void SX1276FskInit( void )
|
||||
{
|
||||
RFState = RF_STATE_IDLE;
|
||||
|
||||
SX1276FskSetDefaults( );
|
||||
|
||||
SX1276ReadBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
|
||||
|
||||
// Set the device in FSK mode and Sleep Mode
|
||||
SX1276->RegOpMode = RF_OPMODE_MODULATIONTYPE_FSK | RF_OPMODE_SLEEP;
|
||||
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
|
||||
|
||||
SX1276->RegPaRamp = RF_PARAMP_MODULATIONSHAPING_01;
|
||||
SX1276Write( REG_PARAMP, SX1276->RegPaRamp );
|
||||
|
||||
SX1276->RegLna = RF_LNA_GAIN_G1;
|
||||
SX1276Write( REG_LNA, SX1276->RegLna );
|
||||
|
||||
if( FskSettings.AfcOn == true )
|
||||
{
|
||||
SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_ON |
|
||||
RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_OFF |
|
||||
RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
|
||||
}
|
||||
|
||||
SX1276->RegPreambleLsb = 8;
|
||||
|
||||
SX1276->RegPreambleDetect = RF_PREAMBLEDETECT_DETECTOR_ON | RF_PREAMBLEDETECT_DETECTORSIZE_2 |
|
||||
RF_PREAMBLEDETECT_DETECTORTOL_10;
|
||||
|
||||
SX1276->RegRssiThresh = 0xFF;
|
||||
|
||||
SX1276->RegSyncConfig = RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON | RF_SYNCCONFIG_PREAMBLEPOLARITY_AA |
|
||||
RF_SYNCCONFIG_SYNC_ON |
|
||||
RF_SYNCCONFIG_SYNCSIZE_4;
|
||||
|
||||
SX1276->RegSyncValue1 = 0x69;
|
||||
SX1276->RegSyncValue2 = 0x81;
|
||||
SX1276->RegSyncValue3 = 0x7E;
|
||||
SX1276->RegSyncValue4 = 0x96;
|
||||
|
||||
SX1276->RegPacketConfig1 = RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RF_PACKETCONFIG1_DCFREE_OFF |
|
||||
( FskSettings.CrcOn << 4 ) | RF_PACKETCONFIG1_CRCAUTOCLEAR_ON |
|
||||
RF_PACKETCONFIG1_ADDRSFILTERING_OFF | RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT;
|
||||
SX1276FskGetPacketCrcOn( ); // Update CrcOn on FskSettings
|
||||
|
||||
SX1276->RegPayloadLength = FskSettings.PayloadLength;
|
||||
|
||||
// we can now update the registers with our configuration
|
||||
SX1276WriteBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
|
||||
|
||||
// then we need to set the RF settings
|
||||
SX1276FskSetRFFrequency( FskSettings.RFFrequency );
|
||||
SX1276FskSetBitrate( FskSettings.Bitrate );
|
||||
SX1276FskSetFdev( FskSettings.Fdev );
|
||||
|
||||
SX1276FskSetDccBw( &SX1276->RegRxBw, 0, FskSettings.RxBw );
|
||||
SX1276FskSetDccBw( &SX1276->RegAfcBw, 0, FskSettings.RxBwAfc );
|
||||
SX1276FskSetRssiOffset( 0 );
|
||||
|
||||
#if( ( MODULE_SX1276RF1IAS == 1 ) || ( MODULE_SX1276RF1KAS == 1 ) )
|
||||
if( FskSettings.RFFrequency > 860000000 )
|
||||
{
|
||||
SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_RFO );
|
||||
SX1276FskSetPa20dBm( false );
|
||||
FskSettings.Power = 14;
|
||||
SX1276FskSetRFPower( FskSettings.Power );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_PABOOST );
|
||||
SX1276FskSetPa20dBm( true );
|
||||
FskSettings.Power = 20;
|
||||
SX1276FskSetRFPower( FskSettings.Power );
|
||||
}
|
||||
#elif( MODULE_SX1276RF1JAS == 1 )
|
||||
if( FskSettings.RFFrequency > 860000000 )
|
||||
{
|
||||
SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_PABOOST );
|
||||
SX1276FskSetPa20dBm( true );
|
||||
FskSettings.Power = 20;
|
||||
SX1276FskSetRFPower( FskSettings.Power );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_RFO );
|
||||
SX1276FskSetPa20dBm( false );
|
||||
FskSettings.Power = 14;
|
||||
SX1276FskSetRFPower( FskSettings.Power );
|
||||
}
|
||||
#endif
|
||||
|
||||
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
|
||||
|
||||
// Calibrate the HF
|
||||
SX1276FskRxCalibrate( );
|
||||
}
|
||||
|
||||
void SX1276FskSetDefaults( void )
|
||||
{
|
||||
// REMARK: See SX1276 datasheet for modified default values.
|
||||
|
||||
SX1276Read( REG_VERSION, &SX1276->RegVersion );
|
||||
}
|
||||
|
||||
void SX1276FskSetOpMode( uint8_t opMode )
|
||||
{
|
||||
static uint8_t opModePrev = RF_OPMODE_STANDBY;
|
||||
static bool antennaSwitchTxOnPrev = true;
|
||||
bool antennaSwitchTxOn = false;
|
||||
|
||||
opModePrev = SX1276->RegOpMode & ~RF_OPMODE_MASK;
|
||||
|
||||
if( opMode != opModePrev )
|
||||
{
|
||||
if( opMode == RF_OPMODE_TRANSMITTER )
|
||||
{
|
||||
antennaSwitchTxOn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
antennaSwitchTxOn = false;
|
||||
}
|
||||
if( antennaSwitchTxOn != antennaSwitchTxOnPrev )
|
||||
{
|
||||
antennaSwitchTxOnPrev = antennaSwitchTxOn;
|
||||
RXTX( antennaSwitchTxOn ); // Antenna switch control
|
||||
}
|
||||
SX1276->RegOpMode = ( SX1276->RegOpMode & RF_OPMODE_MASK ) | opMode;
|
||||
|
||||
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetOpMode( void )
|
||||
{
|
||||
SX1276Read( REG_OPMODE, &SX1276->RegOpMode );
|
||||
|
||||
return SX1276->RegOpMode & ~RF_OPMODE_MASK;
|
||||
}
|
||||
|
||||
int32_t SX1276FskReadFei( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_FEIMSB, &SX1276->RegFeiMsb, 2 ); // Reads the FEI value
|
||||
|
||||
return ( int32_t )( double )( ( ( uint16_t )SX1276->RegFeiMsb << 8 ) | ( uint16_t )SX1276->RegFeiLsb ) * ( double )FREQ_STEP;
|
||||
}
|
||||
|
||||
int32_t SX1276FskReadAfc( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_AFCMSB, &SX1276->RegAfcMsb, 2 ); // Reads the AFC value
|
||||
return ( int32_t )( double )( ( ( uint16_t )SX1276->RegAfcMsb << 8 ) | ( uint16_t )SX1276->RegAfcLsb ) * ( double )FREQ_STEP;
|
||||
}
|
||||
|
||||
uint8_t SX1276FskReadRxGain( void )
|
||||
{
|
||||
SX1276Read( REG_LNA, &SX1276->RegLna );
|
||||
return( SX1276->RegLna >> 5 ) & 0x07;
|
||||
}
|
||||
|
||||
double SX1276FskReadRssi( void )
|
||||
{
|
||||
SX1276Read( REG_RSSIVALUE, &SX1276->RegRssiValue ); // Reads the RSSI value
|
||||
|
||||
return -( double )( ( double )SX1276->RegRssiValue / 2.0 );
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetPacketRxGain( void )
|
||||
{
|
||||
return RxGain;
|
||||
}
|
||||
|
||||
double SX1276FskGetPacketRssi( void )
|
||||
{
|
||||
return RxPacketRssiValue;
|
||||
}
|
||||
|
||||
uint32_t SX1276FskGetPacketAfc( void )
|
||||
{
|
||||
return RxPacketAfcValue;
|
||||
}
|
||||
|
||||
void SX1276FskStartRx( void )
|
||||
{
|
||||
SX1276FskSetRFState( RF_STATE_RX_INIT );
|
||||
}
|
||||
|
||||
void SX1276FskGetRxPacket( void *buffer, uint16_t *size )
|
||||
{
|
||||
*size = RxPacketSize;
|
||||
RxPacketSize = 0;
|
||||
memcpy( ( void * )buffer, ( void * )RFBuffer, ( size_t )*size );
|
||||
}
|
||||
|
||||
void SX1276FskSetTxPacket( const void *buffer, uint16_t size )
|
||||
{
|
||||
TxPacketSize = size;
|
||||
memcpy( ( void * )RFBuffer, buffer, ( size_t )TxPacketSize );
|
||||
|
||||
RFState = RF_STATE_TX_INIT;
|
||||
}
|
||||
|
||||
// Remark: SX1276 must be fully initialized before calling this function
|
||||
uint16_t SX1276FskGetPacketPayloadSize( void )
|
||||
{
|
||||
uint16_t syncSize;
|
||||
uint16_t variableSize;
|
||||
uint16_t addressSize;
|
||||
uint16_t payloadSize;
|
||||
uint16_t crcSize;
|
||||
|
||||
syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
|
||||
variableSize = ( ( SX1276->RegPacketConfig1 & 0x80 ) == 0x80 ) ? 1 : 0;
|
||||
addressSize = ( ( SX1276->RegPacketConfig1 & 0x06 ) != 0x00 ) ? 1 : 0;
|
||||
payloadSize = SX1276->RegPayloadLength;
|
||||
crcSize = ( ( SX1276->RegPacketConfig1 & 0x10 ) == 0x10 ) ? 2 : 0;
|
||||
|
||||
return syncSize + variableSize + addressSize + payloadSize + crcSize;
|
||||
}
|
||||
|
||||
// Remark: SX1276 must be fully initialized before calling this function
|
||||
uint16_t SX1276FskGetPacketHeaderSize( void )
|
||||
{
|
||||
uint16_t preambleSize;
|
||||
uint16_t syncSize;
|
||||
|
||||
preambleSize = ( ( uint16_t )SX1276->RegPreambleMsb << 8 ) | ( uint16_t )SX1276->RegPreambleLsb;
|
||||
syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
|
||||
|
||||
return preambleSize + syncSize;
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetRFState( void )
|
||||
{
|
||||
return RFState;
|
||||
}
|
||||
|
||||
void SX1276FskSetRFState( uint8_t state )
|
||||
{
|
||||
RFState = state;
|
||||
}
|
||||
|
||||
uint32_t SX1276FskProcess( void )
|
||||
{
|
||||
uint32_t result = RF_BUSY;
|
||||
|
||||
switch( RFState )
|
||||
{
|
||||
case RF_STATE_IDLE:
|
||||
break;
|
||||
// Rx management
|
||||
case RF_STATE_RX_INIT:
|
||||
// DIO mapping setup
|
||||
if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_ON ) == RF_PACKETCONFIG1_CRC_ON )
|
||||
{
|
||||
// CrcOk, FifoLevel, SyncAddr, FifoEmpty
|
||||
SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_01 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_11 | RF_DIOMAPPING1_DIO3_00;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PayloadReady, FifoLevel, SyncAddr, FifoEmpty
|
||||
SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_00 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_11 | RF_DIOMAPPING1_DIO3_00;
|
||||
}
|
||||
// Preamble, Data
|
||||
SX1276->RegDioMapping2 = RF_DIOMAPPING2_DIO4_11 | RF_DIOMAPPING2_DIO5_10 | RF_DIOMAPPING2_MAP_PREAMBLEDETECT;
|
||||
SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
|
||||
|
||||
SX1276FskSetOpMode( RF_OPMODE_RECEIVER );
|
||||
|
||||
memset( RFBuffer, 0, ( size_t )RF_BUFFER_SIZE );
|
||||
|
||||
PacketTimeout = ( uint16_t )( round( ( 8.0 * ( ( double )SX1276FskGetPacketPayloadSize( ) ) / ( double )FskSettings.Bitrate ) * 1000.0 ) + 1.0 );
|
||||
PacketTimeout = PacketTimeout + ( PacketTimeout >> 1 ); // Set the Packet timeout as 1.5 times the full payload transmission time
|
||||
|
||||
Preamble2SyncTimeout = PacketTimeout;
|
||||
|
||||
Preamble2SyncTimer = RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
|
||||
SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | 0x20; // 32 bytes of data
|
||||
SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
|
||||
|
||||
PreambleDetected = false;
|
||||
SyncWordDetected = false;
|
||||
PacketDetected = false;
|
||||
RxBytesRead = 0;
|
||||
RxPacketSize = 0;
|
||||
RFState = RF_STATE_RX_SYNC;
|
||||
break;
|
||||
case RF_STATE_RX_SYNC:
|
||||
if( ( DIO4 == 1 ) && ( PreambleDetected == false ) )// Preamble
|
||||
{
|
||||
PreambleDetected = true;
|
||||
Preamble2SyncTimer = GET_TICK_COUNT( );
|
||||
}
|
||||
if( ( DIO2 == 1 ) && ( PreambleDetected == true ) && ( SyncWordDetected == false ) ) // SyncAddr
|
||||
{
|
||||
SyncWordDetected = true;
|
||||
|
||||
RxPacketRssiValue = SX1276FskReadRssi( );
|
||||
|
||||
RxPacketAfcValue = SX1276FskReadAfc( );
|
||||
RxGain = SX1276FskReadRxGain( );
|
||||
|
||||
Preamble2SyncTimer = RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
|
||||
RFState = RF_STATE_RX_RUNNING;
|
||||
}
|
||||
|
||||
// Preamble 2 SyncAddr timeout
|
||||
if( ( SyncWordDetected == false ) && ( PreambleDetected == true ) && ( ( GET_TICK_COUNT( ) - Preamble2SyncTimer ) > Preamble2SyncTimeout ) )
|
||||
{
|
||||
RFState = RF_STATE_RX_INIT;
|
||||
SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
|
||||
}
|
||||
if( ( SyncWordDetected == false ) &&
|
||||
( PreambleDetected == false ) &&
|
||||
( PacketDetected == false ) &&
|
||||
( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout ) )
|
||||
{
|
||||
RFState = RF_STATE_RX_TIMEOUT;
|
||||
}
|
||||
break;
|
||||
case RF_STATE_RX_RUNNING:
|
||||
if( RxPacketSize > RF_BUFFER_SIZE_MAX )
|
||||
{
|
||||
RFState = RF_STATE_RX_LEN_ERROR;
|
||||
break;
|
||||
}
|
||||
#if 1
|
||||
if( DIO1 == 1 ) // FifoLevel
|
||||
{
|
||||
if( ( RxPacketSize == 0 ) && ( RxBytesRead == 0 ) ) // Read received packet size
|
||||
{
|
||||
if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
|
||||
{
|
||||
SX1276ReadFifo( ( uint8_t* )&RxPacketSize, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
RxPacketSize = SX1276->RegPayloadLength;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( RxPacketSize - RxBytesRead ) > ( SX1276->RegFifoThresh & 0x3F ) )
|
||||
{
|
||||
SX1276ReadFifo( ( RFBuffer + RxBytesRead ), ( SX1276->RegFifoThresh & 0x3F ) );
|
||||
RxBytesRead += ( SX1276->RegFifoThresh & 0x3F );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276ReadFifo( ( RFBuffer + RxBytesRead ), RxPacketSize - RxBytesRead );
|
||||
RxBytesRead += ( RxPacketSize - RxBytesRead );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( DIO0 == 1 ) // PayloadReady/CrcOk
|
||||
{
|
||||
RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
if( ( RxPacketSize == 0 ) && ( RxBytesRead == 0 ) ) // Read received packet size
|
||||
{
|
||||
if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
|
||||
{
|
||||
SX1276ReadFifo( ( uint8_t* )&RxPacketSize, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
RxPacketSize = SX1276->RegPayloadLength;
|
||||
}
|
||||
SX1276ReadFifo( RFBuffer + RxBytesRead, RxPacketSize - RxBytesRead );
|
||||
RxBytesRead += ( RxPacketSize - RxBytesRead );
|
||||
PacketDetected = true;
|
||||
RFState = RF_STATE_RX_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276ReadFifo( RFBuffer + RxBytesRead, RxPacketSize - RxBytesRead );
|
||||
RxBytesRead += ( RxPacketSize - RxBytesRead );
|
||||
PacketDetected = true;
|
||||
RFState = RF_STATE_RX_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Packet timeout
|
||||
if( ( PacketDetected == false ) && ( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout ) )
|
||||
{
|
||||
RFState = RF_STATE_RX_TIMEOUT;
|
||||
}
|
||||
break;
|
||||
case RF_STATE_RX_DONE:
|
||||
RxBytesRead = 0;
|
||||
RFState = RF_STATE_RX_INIT;
|
||||
result = RF_RX_DONE;
|
||||
break;
|
||||
case RF_STATE_RX_TIMEOUT:
|
||||
RxBytesRead = 0;
|
||||
RxPacketSize = 0;
|
||||
SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
|
||||
RFState = RF_STATE_RX_INIT;
|
||||
result = RF_RX_TIMEOUT;
|
||||
break;
|
||||
case RF_STATE_RX_LEN_ERROR:
|
||||
RxBytesRead = 0;
|
||||
RxPacketSize = 0;
|
||||
SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig | RF_RXCONFIG_RESTARTRXWITHPLLLOCK );
|
||||
RFState = RF_STATE_RX_INIT;
|
||||
result = RF_LEN_ERROR;
|
||||
break;
|
||||
// Tx management
|
||||
case RF_STATE_TX_INIT:
|
||||
// Packet DIO mapping setup
|
||||
// PacketSent, FifoLevel, FifoFull, TxReady
|
||||
SX1276->RegDioMapping1 = RF_DIOMAPPING1_DIO0_00 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_00 | RF_DIOMAPPING1_DIO3_01;
|
||||
// LowBat, Data
|
||||
SX1276->RegDioMapping2 = RF_DIOMAPPING2_DIO4_00 | RF_DIOMAPPING2_DIO5_10;
|
||||
SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
|
||||
|
||||
SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | 0x18; // 24 bytes of data
|
||||
SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
|
||||
|
||||
SX1276FskSetOpMode( RF_OPMODE_TRANSMITTER );
|
||||
RFState = RF_STATE_TX_READY_WAIT;
|
||||
TxBytesSent = 0;
|
||||
break;
|
||||
case RF_STATE_TX_READY_WAIT:
|
||||
if( DIO3 == 1 ) // TxReady
|
||||
{
|
||||
if( ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) == RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE )
|
||||
{
|
||||
SX1276WriteFifo( ( uint8_t* )&TxPacketSize, 1 );
|
||||
}
|
||||
|
||||
if( ( TxPacketSize > 0 ) && ( TxPacketSize <= 64 ) )
|
||||
{
|
||||
DataChunkSize = TxPacketSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataChunkSize = 32;
|
||||
}
|
||||
|
||||
SX1276WriteFifo( RFBuffer, DataChunkSize );
|
||||
TxBytesSent += DataChunkSize;
|
||||
TxTimeoutTimer = GET_TICK_COUNT( );
|
||||
RFState = RF_STATE_TX_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
case RF_STATE_TX_RUNNING:
|
||||
if( DIO1 == 0 ) // FifoLevel below thresold
|
||||
{
|
||||
if( ( TxPacketSize - TxBytesSent ) > DataChunkSize )
|
||||
{
|
||||
SX1276WriteFifo( ( RFBuffer + TxBytesSent ), DataChunkSize );
|
||||
TxBytesSent += DataChunkSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we write the last chunk of data
|
||||
SX1276WriteFifo( RFBuffer + TxBytesSent, TxPacketSize - TxBytesSent );
|
||||
TxBytesSent += TxPacketSize - TxBytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
if( DIO0 == 1 ) // PacketSent
|
||||
{
|
||||
TxTimeoutTimer = GET_TICK_COUNT( );
|
||||
RFState = RF_STATE_TX_DONE;
|
||||
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
|
||||
}
|
||||
|
||||
// Packet timeout
|
||||
if( ( GET_TICK_COUNT( ) - TxTimeoutTimer ) > TICK_RATE_MS( 1000 ) )
|
||||
{
|
||||
RFState = RF_STATE_TX_TIMEOUT;
|
||||
}
|
||||
break;
|
||||
case RF_STATE_TX_DONE:
|
||||
RFState = RF_STATE_IDLE;
|
||||
result = RF_TX_DONE;
|
||||
break;
|
||||
case RF_STATE_TX_TIMEOUT:
|
||||
RFState = RF_STATE_IDLE;
|
||||
result = RF_TX_TIMEOUT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_SX1276_RADIO
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-FskMisc.c
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-FskMisc.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if defined( USE_SX1276_RADIO )
|
||||
|
||||
#include "sx1276-Hal.h"
|
||||
#include "sx1276.h"
|
||||
|
||||
#include "sx1276-Fsk.h"
|
||||
#include "sx1276-FskMisc.h"
|
||||
|
||||
extern tFskSettings FskSettings;
|
||||
|
||||
void SX1276FskSetRFFrequency( uint32_t freq )
|
||||
{
|
||||
FskSettings.RFFrequency = freq;
|
||||
|
||||
freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP );
|
||||
SX1276->RegFrfMsb = ( uint8_t )( ( freq >> 16 ) & 0xFF );
|
||||
SX1276->RegFrfMid = ( uint8_t )( ( freq >> 8 ) & 0xFF );
|
||||
SX1276->RegFrfLsb = ( uint8_t )( freq & 0xFF );
|
||||
SX1276WriteBuffer( REG_FRFMSB, &SX1276->RegFrfMsb, 3 );
|
||||
}
|
||||
|
||||
uint32_t SX1276FskGetRFFrequency( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_FRFMSB, &SX1276->RegFrfMsb, 3 );
|
||||
FskSettings.RFFrequency = ( ( uint32_t )SX1276->RegFrfMsb << 16 ) | ( ( uint32_t )SX1276->RegFrfMid << 8 ) | ( ( uint32_t )SX1276->RegFrfLsb );
|
||||
FskSettings.RFFrequency = ( uint32_t )( ( double )FskSettings.RFFrequency * ( double )FREQ_STEP );
|
||||
|
||||
return FskSettings.RFFrequency;
|
||||
}
|
||||
|
||||
void SX1276FskRxCalibrate( void )
|
||||
{
|
||||
// the function RadioRxCalibrate is called just after the reset so all register are at their default values
|
||||
uint8_t regPaConfigInitVal;
|
||||
uint32_t initialFreq;
|
||||
|
||||
// save register values;
|
||||
SX1276Read( REG_PACONFIG, ®PaConfigInitVal );
|
||||
initialFreq = SX1276FskGetRFFrequency( );
|
||||
|
||||
// Cut the PA just in case
|
||||
SX1276->RegPaConfig = 0x00; // RFO output, power = -1 dBm
|
||||
SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
|
||||
|
||||
// Set Frequency in HF band
|
||||
SX1276FskSetRFFrequency( 860000000 );
|
||||
|
||||
// Rx chain re-calibration workaround
|
||||
SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
|
||||
SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START;
|
||||
SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
|
||||
|
||||
SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
|
||||
// rx_cal_run goes low when calibration in finished
|
||||
while( ( SX1276->RegImageCal & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING )
|
||||
{
|
||||
SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
|
||||
}
|
||||
|
||||
// reload saved values into the registers
|
||||
SX1276->RegPaConfig = regPaConfigInitVal;
|
||||
SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
|
||||
|
||||
SX1276FskSetRFFrequency( initialFreq );
|
||||
|
||||
}
|
||||
|
||||
void SX1276FskSetBitrate( uint32_t bitrate )
|
||||
{
|
||||
FskSettings.Bitrate = bitrate;
|
||||
|
||||
bitrate = ( uint16_t )( ( double )XTAL_FREQ / ( double )bitrate );
|
||||
SX1276->RegBitrateMsb = ( uint8_t )( bitrate >> 8 );
|
||||
SX1276->RegBitrateLsb = ( uint8_t )( bitrate & 0xFF );
|
||||
SX1276WriteBuffer( REG_BITRATEMSB, &SX1276->RegBitrateMsb, 2 );
|
||||
}
|
||||
|
||||
uint32_t SX1276FskGetBitrate( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_BITRATEMSB, &SX1276->RegBitrateMsb, 2 );
|
||||
FskSettings.Bitrate = ( ( ( uint32_t )SX1276->RegBitrateMsb << 8 ) | ( ( uint32_t )SX1276->RegBitrateLsb ) );
|
||||
FskSettings.Bitrate = ( uint16_t )( ( double )XTAL_FREQ / ( double )FskSettings.Bitrate );
|
||||
|
||||
return FskSettings.Bitrate;
|
||||
}
|
||||
|
||||
void SX1276FskSetFdev( uint32_t fdev )
|
||||
{
|
||||
FskSettings.Fdev = fdev;
|
||||
|
||||
SX1276Read( REG_FDEVMSB, &SX1276->RegFdevMsb );
|
||||
|
||||
fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP );
|
||||
SX1276->RegFdevMsb = ( ( SX1276->RegFdevMsb & RF_FDEVMSB_FDEV_MASK ) | ( ( ( uint8_t )( fdev >> 8 ) ) & ~RF_FDEVMSB_FDEV_MASK ) );
|
||||
SX1276->RegFdevLsb = ( uint8_t )( fdev & 0xFF );
|
||||
SX1276WriteBuffer( REG_FDEVMSB, &SX1276->RegFdevMsb, 2 );
|
||||
}
|
||||
|
||||
uint32_t SX1276FskGetFdev( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_FDEVMSB, &SX1276->RegFdevMsb, 2 );
|
||||
FskSettings.Fdev = ( ( ( uint32_t )( ( SX1276->RegFdevMsb << 8 ) & ~RF_FDEVMSB_FDEV_MASK ) ) | ( ( uint32_t )SX1276->RegFdevLsb ) );
|
||||
FskSettings.Fdev = ( uint16_t )( ( double )FskSettings.Fdev * ( double )FREQ_STEP );
|
||||
|
||||
return FskSettings.Fdev;
|
||||
}
|
||||
|
||||
void SX1276FskSetRFPower( int8_t power )
|
||||
{
|
||||
SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
|
||||
SX1276Read( REG_PADAC, &SX1276->RegPaDac );
|
||||
|
||||
if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( ( SX1276->RegPaDac & 0x87 ) == 0x87 )
|
||||
{
|
||||
if( power < 5 )
|
||||
{
|
||||
power = 5;
|
||||
}
|
||||
if( power > 20 )
|
||||
{
|
||||
power = 20;
|
||||
}
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( power < 2 )
|
||||
{
|
||||
power = 2;
|
||||
}
|
||||
if( power > 17 )
|
||||
{
|
||||
power = 17;
|
||||
}
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( power < -1 )
|
||||
{
|
||||
power = -1;
|
||||
}
|
||||
if( power > 14 )
|
||||
{
|
||||
power = 14;
|
||||
}
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276->RegPaConfig = ( SX1276->RegPaConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
|
||||
}
|
||||
SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
|
||||
FskSettings.Power = power;
|
||||
}
|
||||
|
||||
int8_t SX1276FskGetRFPower( void )
|
||||
{
|
||||
SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
|
||||
SX1276Read( REG_PADAC, &SX1276->RegPaDac );
|
||||
|
||||
if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( ( SX1276->RegPaDac & 0x07 ) == 0x07 )
|
||||
{
|
||||
FskSettings.Power = 5 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
else
|
||||
{
|
||||
FskSettings.Power = 2 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FskSettings.Power = -1 + ( SX1276->RegPaConfig & ~RF_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
return FskSettings.Power;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the Rx bandwidth with the mantisse and exponent
|
||||
*
|
||||
* \param [IN] mantisse Mantisse of the bandwidth value
|
||||
* \param [IN] exponent Exponent of the bandwidth value
|
||||
* \retval bandwidth Computed bandwidth
|
||||
*/
|
||||
static uint32_t SX1276FskComputeRxBw( uint8_t mantisse, uint8_t exponent )
|
||||
{
|
||||
// rxBw
|
||||
if( ( SX1276->RegOpMode & RF_OPMODE_MODULATIONTYPE_FSK ) == RF_OPMODE_MODULATIONTYPE_FSK )
|
||||
{
|
||||
return ( uint32_t )( ( double )XTAL_FREQ / ( mantisse * ( double )pow( 2, exponent + 2 ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( uint32_t )( ( double )XTAL_FREQ / ( mantisse * ( double )pow( 2, exponent + 3 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the mantisse and exponent from the bandwitdh value
|
||||
*
|
||||
* \param [IN] rxBwValue Bandwidth value
|
||||
* \param [OUT] mantisse Mantisse of the bandwidth value
|
||||
* \param [OUT] exponent Exponent of the bandwidth value
|
||||
*/
|
||||
static void SX1276FskComputeRxBwMantExp( uint32_t rxBwValue, uint8_t* mantisse, uint8_t* exponent )
|
||||
{
|
||||
uint8_t tmpExp = 0;
|
||||
uint8_t tmpMant = 0;
|
||||
|
||||
double tmpRxBw = 0;
|
||||
double rxBwMin = 10e6;
|
||||
|
||||
for( tmpExp = 0; tmpExp < 8; tmpExp++ )
|
||||
{
|
||||
for( tmpMant = 16; tmpMant <= 24; tmpMant += 4 )
|
||||
{
|
||||
if( ( SX1276->RegOpMode & RF_OPMODE_MODULATIONTYPE_FSK ) == RF_OPMODE_MODULATIONTYPE_FSK )
|
||||
{
|
||||
tmpRxBw = ( double )XTAL_FREQ / ( tmpMant * ( double )pow( 2, tmpExp + 2 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpRxBw = ( double )XTAL_FREQ / ( tmpMant * ( double )pow( 2, tmpExp + 3 ) );
|
||||
}
|
||||
if( fabs( tmpRxBw - rxBwValue ) < rxBwMin )
|
||||
{
|
||||
rxBwMin = fabs( tmpRxBw - rxBwValue );
|
||||
*mantisse = tmpMant;
|
||||
*exponent = tmpExp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276FskSetDccBw( uint8_t* reg, uint32_t dccValue, uint32_t rxBwValue )
|
||||
{
|
||||
uint8_t mantisse = 0;
|
||||
uint8_t exponent = 0;
|
||||
|
||||
if( reg == &SX1276->RegRxBw )
|
||||
{
|
||||
*reg = ( uint8_t )dccValue & 0x60;
|
||||
}
|
||||
else
|
||||
{
|
||||
*reg = 0;
|
||||
}
|
||||
|
||||
SX1276FskComputeRxBwMantExp( rxBwValue, &mantisse, &exponent );
|
||||
|
||||
switch( mantisse )
|
||||
{
|
||||
case 16:
|
||||
*reg |= ( uint8_t )( 0x00 | ( exponent & 0x07 ) );
|
||||
break;
|
||||
case 20:
|
||||
*reg |= ( uint8_t )( 0x08 | ( exponent & 0x07 ) );
|
||||
break;
|
||||
case 24:
|
||||
*reg |= ( uint8_t )( 0x10 | ( exponent & 0x07 ) );
|
||||
break;
|
||||
default:
|
||||
// Something went terribely wrong
|
||||
break;
|
||||
}
|
||||
|
||||
if( reg == &SX1276->RegRxBw )
|
||||
{
|
||||
SX1276Write( REG_RXBW, *reg );
|
||||
FskSettings.RxBw = rxBwValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276Write( REG_AFCBW, *reg );
|
||||
FskSettings.RxBwAfc = rxBwValue;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SX1276FskGetBw( uint8_t* reg )
|
||||
{
|
||||
uint32_t rxBwValue = 0;
|
||||
uint8_t mantisse = 0;
|
||||
switch( ( *reg & 0x18 ) >> 3 )
|
||||
{
|
||||
case 0:
|
||||
mantisse = 16;
|
||||
break;
|
||||
case 1:
|
||||
mantisse = 20;
|
||||
break;
|
||||
case 2:
|
||||
mantisse = 24;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rxBwValue = SX1276FskComputeRxBw( mantisse, ( uint8_t )*reg & 0x07 );
|
||||
if( reg == &SX1276->RegRxBw )
|
||||
{
|
||||
return FskSettings.RxBw = rxBwValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FskSettings.RxBwAfc = rxBwValue;
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276FskSetPacketCrcOn( bool enable )
|
||||
{
|
||||
SX1276Read( REG_PACKETCONFIG1, &SX1276->RegPacketConfig1 );
|
||||
SX1276->RegPacketConfig1 = ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_MASK ) | ( enable << 4 );
|
||||
SX1276Write( REG_PACKETCONFIG1, SX1276->RegPacketConfig1 );
|
||||
FskSettings.CrcOn = enable;
|
||||
}
|
||||
|
||||
bool SX1276FskGetPacketCrcOn( void )
|
||||
{
|
||||
SX1276Read( REG_PACKETCONFIG1, &SX1276->RegPacketConfig1 );
|
||||
FskSettings.CrcOn = ( SX1276->RegPacketConfig1 & RF_PACKETCONFIG1_CRC_ON ) >> 4;
|
||||
return FskSettings.CrcOn;
|
||||
}
|
||||
|
||||
void SX1276FskSetAfcOn( bool enable )
|
||||
{
|
||||
SX1276Read( REG_RXCONFIG, &SX1276->RegRxConfig );
|
||||
SX1276->RegRxConfig = ( SX1276->RegRxConfig & RF_RXCONFIG_AFCAUTO_MASK ) | ( enable << 4 );
|
||||
SX1276Write( REG_RXCONFIG, SX1276->RegRxConfig );
|
||||
FskSettings.AfcOn = enable;
|
||||
}
|
||||
|
||||
bool SX1276FskGetAfcOn( void )
|
||||
{
|
||||
SX1276Read( REG_RXCONFIG, &SX1276->RegRxConfig );
|
||||
FskSettings.AfcOn = ( SX1276->RegRxConfig & RF_RXCONFIG_AFCAUTO_ON ) >> 4;
|
||||
return FskSettings.AfcOn;
|
||||
}
|
||||
|
||||
void SX1276FskSetPayloadLength( uint8_t value )
|
||||
{
|
||||
SX1276->RegPayloadLength = value;
|
||||
SX1276Write( REG_PAYLOADLENGTH, SX1276->RegPayloadLength );
|
||||
FskSettings.PayloadLength = value;
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetPayloadLength( void )
|
||||
{
|
||||
SX1276Read( REG_PAYLOADLENGTH, &SX1276->RegPayloadLength );
|
||||
FskSettings.PayloadLength = SX1276->RegPayloadLength;
|
||||
return FskSettings.PayloadLength;
|
||||
}
|
||||
|
||||
void SX1276FskSetPa20dBm( bool enale )
|
||||
{
|
||||
SX1276Read( REG_PADAC, &SX1276->RegPaDac );
|
||||
SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
|
||||
|
||||
if( ( SX1276->RegPaConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( enale == true )
|
||||
{
|
||||
SX1276->RegPaDac = 0x87;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276->RegPaDac = 0x84;
|
||||
}
|
||||
SX1276Write( REG_PADAC, SX1276->RegPaDac );
|
||||
}
|
||||
|
||||
bool SX1276FskGetPa20dBm( void )
|
||||
{
|
||||
SX1276Read( REG_PADAC, &SX1276->RegPaDac );
|
||||
|
||||
return ( ( SX1276->RegPaDac & 0x07 ) == 0x07 ) ? true : false;
|
||||
}
|
||||
|
||||
void SX1276FskSetPAOutput( uint8_t outputPin )
|
||||
{
|
||||
SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
|
||||
SX1276->RegPaConfig = (SX1276->RegPaConfig & RF_PACONFIG_PASELECT_MASK ) | outputPin;
|
||||
SX1276Write( REG_PACONFIG, SX1276->RegPaConfig );
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetPAOutput( void )
|
||||
{
|
||||
SX1276Read( REG_PACONFIG, &SX1276->RegPaConfig );
|
||||
return SX1276->RegPaConfig & ~RF_PACONFIG_PASELECT_MASK;
|
||||
}
|
||||
|
||||
|
||||
void SX1276FskSetPaRamp( uint8_t value )
|
||||
{
|
||||
SX1276Read( REG_PARAMP, &SX1276->RegPaRamp );
|
||||
SX1276->RegPaRamp = ( SX1276->RegPaRamp & RF_PARAMP_MASK ) | ( value & ~RF_PARAMP_MASK );
|
||||
SX1276Write( REG_PARAMP, SX1276->RegPaRamp );
|
||||
}
|
||||
|
||||
uint8_t SX1276FskGetPaRamp( void )
|
||||
{
|
||||
SX1276Read( REG_PARAMP, &SX1276->RegPaRamp );
|
||||
return SX1276->RegPaRamp & ~RF_PARAMP_MASK;
|
||||
}
|
||||
|
||||
void SX1276FskSetRssiOffset( int8_t offset )
|
||||
{
|
||||
SX1276Read( REG_RSSICONFIG, &SX1276->RegRssiConfig );
|
||||
if( offset < 0 )
|
||||
{
|
||||
offset = ( ~offset & 0x1F );
|
||||
offset += 1;
|
||||
offset = -offset;
|
||||
}
|
||||
SX1276->RegRssiConfig |= ( uint8_t )( ( offset & 0x1F ) << 3 );
|
||||
SX1276Write( REG_RSSICONFIG, SX1276->RegRssiConfig );
|
||||
}
|
||||
|
||||
int8_t SX1276FskGetRssiOffset( void )
|
||||
{
|
||||
int8_t offset;
|
||||
SX1276Read( REG_RSSICONFIG, &SX1276->RegRssiConfig );
|
||||
offset = SX1276->RegRssiConfig >> 3;
|
||||
if( ( offset & 0x10 ) == 0x10 )
|
||||
{
|
||||
offset = ( ~offset & 0x1F );
|
||||
offset += 1;
|
||||
offset = -offset;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int8_t SX1276FskGetRawTemp( void )
|
||||
{
|
||||
int8_t temp = 0;
|
||||
uint8_t previousOpMode;
|
||||
uint32_t startTick;
|
||||
|
||||
// Enable Temperature reading
|
||||
SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
|
||||
SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_TEMPMONITOR_MASK ) | RF_IMAGECAL_TEMPMONITOR_ON;
|
||||
SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
|
||||
|
||||
// save current Op Mode
|
||||
SX1276Read( REG_OPMODE, &SX1276->RegOpMode );
|
||||
previousOpMode = SX1276->RegOpMode;
|
||||
|
||||
// put device in FSK RxSynth
|
||||
SX1276->RegOpMode = RF_OPMODE_SYNTHESIZER_RX;
|
||||
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
|
||||
|
||||
// Wait 1ms
|
||||
startTick = GET_TICK_COUNT( );
|
||||
while( ( GET_TICK_COUNT( ) - startTick ) < TICK_RATE_MS( 1 ) );
|
||||
|
||||
// Disable Temperature reading
|
||||
SX1276Read( REG_IMAGECAL, &SX1276->RegImageCal );
|
||||
SX1276->RegImageCal = ( SX1276->RegImageCal & RF_IMAGECAL_TEMPMONITOR_MASK ) | RF_IMAGECAL_TEMPMONITOR_OFF;
|
||||
SX1276Write( REG_IMAGECAL, SX1276->RegImageCal );
|
||||
|
||||
// Read temperature
|
||||
SX1276Read( REG_TEMP, &SX1276->RegTemp );
|
||||
|
||||
temp = SX1276->RegTemp & 0x7F;
|
||||
|
||||
if( ( SX1276->RegTemp & 0x80 ) == 0x80 )
|
||||
{
|
||||
temp *= -1;
|
||||
}
|
||||
|
||||
// Reload previous Op Mode
|
||||
SX1276Write( REG_OPMODE, previousOpMode );
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
int8_t SX1276FskCalibreateTemp( int8_t actualTemp )
|
||||
{
|
||||
return actualTemp - SX1276FskGetRawTemp( );
|
||||
}
|
||||
|
||||
int8_t SX1276FskGetTemp( int8_t compensationFactor )
|
||||
{
|
||||
return SX1276FskGetRawTemp( ) + compensationFactor;
|
||||
}
|
||||
|
||||
#endif // USE_SX1276_RADIO
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-FskMisc.h
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.B2
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-FskMisc.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#ifndef __SX1276_FSK_MISC_H__
|
||||
#define __SX1276_FSK_MISC_H__
|
||||
|
||||
/*!
|
||||
* \brief Writes the new RF frequency value
|
||||
*
|
||||
* \param [IN] freq New RF frequency value in [Hz]
|
||||
*/
|
||||
void SX1276FskSetRFFrequency( uint32_t freq );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current RF frequency value
|
||||
*
|
||||
* \retval freq Current RF frequency value in [Hz]
|
||||
*/
|
||||
uint32_t SX1276FskGetRFFrequency( void );
|
||||
|
||||
/*!
|
||||
* \brief Calibrate RSSI and I/Q mismatch for HF
|
||||
*
|
||||
* \retval none
|
||||
*/
|
||||
void SX1276FskRxCalibrate( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new bitrate value
|
||||
*
|
||||
* \param [IN] bitrate New bitrate value in [bps]
|
||||
*/
|
||||
void SX1276FskSetBitrate( uint32_t bitrate );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current bitrate value
|
||||
*
|
||||
* \retval bitrate Current bitrate value in [bps]
|
||||
*/
|
||||
uint32_t SX1276FskGetBitrate( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new frequency deviation value
|
||||
*
|
||||
* \param [IN] fdev New frequency deviation value in [Hz]
|
||||
*/
|
||||
void SX1276FskSetFdev( uint32_t fdev );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current frequency deviation value
|
||||
*
|
||||
* \retval fdev Current frequency deviation value in [Hz]
|
||||
*/
|
||||
uint32_t SX1276FskGetFdev( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new RF output power value
|
||||
*
|
||||
* \param [IN] power New output power value in [dBm]
|
||||
*/
|
||||
void SX1276FskSetRFPower( int8_t power );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current RF output power value
|
||||
*
|
||||
* \retval power Current output power value in [dBm]
|
||||
*/
|
||||
int8_t SX1276FskGetRFPower( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the DC offset canceller and Rx bandwidth values
|
||||
*
|
||||
* \remark For SX1276 there is no DCC setting. dccValue should be 0
|
||||
* ie: SX1276SetDccBw( &SX1276.RegRxBw, 0, 62500 );
|
||||
*
|
||||
* \param [IN] reg Register pointer to either SX1231.RegRxBw or SX1231.RegAfcBw
|
||||
* \param [IN] dccValue New DC offset canceller value in [Hz] ( SX1231 only )
|
||||
* \param [IN] rxBwValue New Rx bandwidth value in [Hz]
|
||||
*/
|
||||
void SX1276FskSetDccBw( uint8_t* reg, uint32_t dccValue, uint32_t rxBwValue );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current bandwidth setting
|
||||
*
|
||||
* \param [IN] reg Register pointer to either SX1231.RegRxBw or SX1231.RegAfcBw
|
||||
*
|
||||
* \retval bandwidth Bandwidth value
|
||||
*/
|
||||
uint32_t SX1276FskGetBw( uint8_t* reg );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables CRC
|
||||
*
|
||||
* \param [IN] enable CRC enable/disable
|
||||
*/
|
||||
void SX1276FskSetPacketCrcOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current CRC Enable/Disbale value
|
||||
*
|
||||
* \retval enable Current CRC Enable/Disbale value
|
||||
*/
|
||||
bool SX1276FskGetPacketCrcOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables AFC
|
||||
*
|
||||
* \param [IN] enable AFC enable/disable
|
||||
*/
|
||||
void SX1276FskSetAfcOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current AFC Enable/Disbale value
|
||||
*
|
||||
* \retval enable Current AFC Enable/Disbale value
|
||||
*/
|
||||
bool SX1276FskGetAfcOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new payload length value
|
||||
*
|
||||
* \param [IN] value New payload length value
|
||||
*/
|
||||
void SX1276FskSetPayloadLength( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current payload length value
|
||||
*
|
||||
* \retval value Current payload length value
|
||||
*/
|
||||
uint8_t SX1276FskGetPayloadLength( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables the 20 dBm PA
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
void SX1276FskSetPa20dBm( bool enale );
|
||||
|
||||
/*!
|
||||
* \brief Gets the current 20 dBm PA status
|
||||
*
|
||||
* \retval enable [true, false]
|
||||
*/
|
||||
bool SX1276FskGetPa20dBm( void );
|
||||
|
||||
/*!
|
||||
* \brief Set the RF Output pin
|
||||
*
|
||||
* \param [IN] RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
|
||||
*/
|
||||
void SX1276FskSetPAOutput( uint8_t outputPin );
|
||||
|
||||
/*!
|
||||
* \brief Gets the used RF Ouptu pin
|
||||
*
|
||||
* \retval RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
|
||||
*/
|
||||
uint8_t SX1276FskGetPAOutput( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new PA rise/fall time of ramp up/down value
|
||||
*
|
||||
* \param [IN] value New PaRamp value
|
||||
*/
|
||||
void SX1276FskSetPaRamp( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current PA rise/fall time of ramp up/down value
|
||||
*
|
||||
* \retval value Current PaRamp value
|
||||
*/
|
||||
uint8_t SX1276FskGetPaRamp( void );
|
||||
|
||||
/*!
|
||||
* \brief Applies an offset to the RSSI. Compensates board components
|
||||
*
|
||||
* \param [IN] offset Offset to be applied (+/-)
|
||||
*/
|
||||
void SX1276FskSetRssiOffset( int8_t offset );
|
||||
|
||||
/*!
|
||||
* \brief Gets the current RSSI offset.
|
||||
*
|
||||
* \retval offset Current offset (+/-)
|
||||
*/
|
||||
int8_t SX1276FskGetRssiOffset( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new value for the preamble size
|
||||
*
|
||||
* \param [IN] size New value of pramble size
|
||||
*/
|
||||
void SX1276FskSetPreambleSize( uint16_t size );
|
||||
|
||||
/*!
|
||||
* Reads the raw temperature
|
||||
* \retval temperature New raw temperature reading in 2's complement format
|
||||
*/
|
||||
int8_t SX1276FskGetRawTemp( void );
|
||||
|
||||
/*!
|
||||
* Computes the temperature compensation factor
|
||||
* \param [IN] actualTemp Actual temperature measured by an external device
|
||||
* \retval compensationFactor Computed compensation factor
|
||||
*/
|
||||
int8_t SX1276FskCalibreateTemp( int8_t actualTemp );
|
||||
|
||||
/*!
|
||||
* Gets the actual compensated temperature
|
||||
* \param [IN] compensationFactor Return value of the calibration function
|
||||
* \retval New compensated temperature value
|
||||
*/
|
||||
int8_t SX1276FskGetTemp( int8_t compensationFactor );
|
||||
|
||||
#endif //__SX1276_FSK_MISC_H__
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-Hal.h
|
||||
* \brief SX1276 Hardware Abstraction Layer
|
||||
*
|
||||
* \version 2.0.B2
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-Hal.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#ifndef __SX1276_HAL_H__
|
||||
#define __SX1276_HAL_H__
|
||||
#include "platform.h"
|
||||
|
||||
/*!
|
||||
* DIO state read functions mapping
|
||||
*/
|
||||
#define DIO0 SX1276ReadDio0( )
|
||||
#define DIO1 SX1276ReadDio1( )
|
||||
#define DIO2 SX1276ReadDio2( )
|
||||
#define DIO3 SX1276ReadDio3( )
|
||||
#define DIO4 SX1276ReadDio4( )
|
||||
#define DIO5 SX1276ReadDio5( )
|
||||
|
||||
// RXTX pin control see errata note
|
||||
#define RXTX( txEnable ) SX1276WriteRxTx( txEnable );
|
||||
|
||||
#define GET_TICK_COUNT( ) CurrentTicksGain()
|
||||
#define TICK_RATE_MS( ms ) ( ms )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RADIO_RESET_OFF,
|
||||
RADIO_RESET_ON,
|
||||
}tRadioResetState;
|
||||
|
||||
/*!
|
||||
* \brief Initializes the radio interface I/Os
|
||||
*/
|
||||
void SX1276InitIo( void );
|
||||
|
||||
/*!
|
||||
* \brief Set the radio reset pin state
|
||||
*
|
||||
* \param state New reset pin state
|
||||
*/
|
||||
void SX1276SetReset( uint8_t state );
|
||||
|
||||
/*!
|
||||
* \brief Writes the radio register at the specified address
|
||||
*
|
||||
* \param [IN]: addr Register address
|
||||
* \param [IN]: data New register value
|
||||
*/
|
||||
void SX1276Write( uint8_t addr, uint8_t data );
|
||||
|
||||
/*!
|
||||
* \brief Reads the radio register at the specified address
|
||||
*
|
||||
* \param [IN]: addr Register address
|
||||
* \param [OUT]: data Register value
|
||||
*/
|
||||
void SX1276Read( uint8_t addr, uint8_t *data );
|
||||
|
||||
/*!
|
||||
* \brief Writes multiple radio registers starting at address
|
||||
*
|
||||
* \param [IN] addr First Radio register address
|
||||
* \param [IN] buffer Buffer containing the new register's values
|
||||
* \param [IN] size Number of registers to be written
|
||||
*/
|
||||
void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
|
||||
|
||||
/*!
|
||||
* \brief Reads multiple radio registers starting at address
|
||||
*
|
||||
* \param [IN] addr First Radio register address
|
||||
* \param [OUT] buffer Buffer where to copy the registers data
|
||||
* \param [IN] size Number of registers to be read
|
||||
*/
|
||||
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
|
||||
|
||||
/*!
|
||||
* \brief Writes the buffer contents to the radio FIFO
|
||||
*
|
||||
* \param [IN] buffer Buffer containing data to be put on the FIFO.
|
||||
* \param [IN] size Number of bytes to be written to the FIFO
|
||||
*/
|
||||
void SX1276WriteFifo( uint8_t *buffer, uint8_t size );
|
||||
|
||||
/*!
|
||||
* \brief Reads the contents of the radio FIFO
|
||||
*
|
||||
* \param [OUT] buffer Buffer where to copy the FIFO read data.
|
||||
* \param [IN] size Number of bytes to be read from the FIFO
|
||||
*/
|
||||
void SX1276ReadFifo( uint8_t *buffer, uint8_t size );
|
||||
|
||||
/*!
|
||||
* \brief Gets the SX1276 DIO0 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio0( void );
|
||||
|
||||
/*!
|
||||
* \brief Ge// USE_SX1276_RADIOts the SX1276 DIO1 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio1( void );
|
||||
|
||||
/*!
|
||||
* \brief Gets the SX1276 DIO2 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio2( void );
|
||||
|
||||
/*!
|
||||
* \brief Gets the SX1276 DIO3 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio3( void );
|
||||
|
||||
/*!
|
||||
* \brief Gets the SX1276 DIO4 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio4( void );
|
||||
|
||||
/*!
|
||||
* \brief Gets the SX1276 DIO5 hardware pin status
|
||||
*
|
||||
* \retval status Current hardware pin status [1, 0]
|
||||
*/
|
||||
inline uint8_t SX1276ReadDio5( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the external RxTx pin value
|
||||
*
|
||||
* \remark see errata note
|
||||
*
|
||||
* \param [IN] txEnable [1: Tx, 0: Rx]
|
||||
*/
|
||||
inline void SX1276WriteRxTx( uint8_t txEnable );
|
||||
|
||||
#endif //__SX1276_HAL_H__
|
||||
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Original Copyright (C) SEMTECH S.A.
|
||||
* Modified Copyright (C) 2020 AIIT XUOS Lab
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-LoRa.c
|
||||
* \brief SX1276 RF chip driver mode LoRa
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-LoRa.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if defined( USE_SX1276_RADIO )
|
||||
#include "radio.h"
|
||||
#include "sx1276-Hal.h"
|
||||
#include "sx1276.h"
|
||||
#include "sx1276-LoRaMisc.h"
|
||||
#include "sx1276-LoRa.h"
|
||||
|
||||
#define LoRa_FREQENCY 433000000
|
||||
|
||||
#define RSSI_OFFSET_LF -155.0
|
||||
#define RSSI_OFFSET_HF -150.0
|
||||
|
||||
#define NOISE_ABSOLUTE_ZERO -174.0
|
||||
#define NOISE_FIGURE_LF 4.0
|
||||
#define NOISE_FIGURE_HF 6.0
|
||||
|
||||
volatile uint32 TickCounter = 0;
|
||||
|
||||
uint32 Tx_Time_Start,Tx_Time_End;
|
||||
uint32 Rx_Time_Start,Rx_Time_End;
|
||||
//Signal bandwidth, used to calculate RSSI
|
||||
const double SignalBwLog[] =
|
||||
{
|
||||
3.8927900303521316335038277369285, // 7.8 kHz
|
||||
4.0177301567005500940384239336392, // 10.4 kHz
|
||||
4.193820026016112828717566631653, // 15.6 kHz
|
||||
4.31875866931372901183597627752391, // 20.8 kHz
|
||||
4.4948500216800940239313055263775, // 31.2 kHz
|
||||
4.6197891057238405255051280399961, // 41.6 kHz
|
||||
4.795880017344075219145044421102, // 62.5 kHz
|
||||
5.0969100130080564143587833158265, // 125 kHz
|
||||
5.397940008672037609572522210551, // 250 kHz
|
||||
5.6989700043360188047862611052755 // 500 kHz
|
||||
};
|
||||
|
||||
//These values need testing
|
||||
const double RssiOffsetLF[] =
|
||||
{
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
-155.0,
|
||||
};
|
||||
|
||||
//These values need testing
|
||||
const double RssiOffsetHF[] =
|
||||
{
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
-150.0,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Frequency hopping frequencies table
|
||||
*/
|
||||
const int32_t HoppingFrequencies[] =
|
||||
{
|
||||
916500000,
|
||||
923500000,
|
||||
906500000,
|
||||
917500000,
|
||||
917500000,
|
||||
909000000,
|
||||
903000000,
|
||||
916000000,
|
||||
912500000,
|
||||
926000000,
|
||||
925000000,
|
||||
909500000,
|
||||
913000000,
|
||||
918500000,
|
||||
918500000,
|
||||
902500000,
|
||||
911500000,
|
||||
926500000,
|
||||
902500000,
|
||||
922000000,
|
||||
924000000,
|
||||
903500000,
|
||||
913000000,
|
||||
922000000,
|
||||
926000000,
|
||||
910000000,
|
||||
920000000,
|
||||
922500000,
|
||||
911000000,
|
||||
922000000,
|
||||
909500000,
|
||||
926000000,
|
||||
922000000,
|
||||
918000000,
|
||||
925500000,
|
||||
908000000,
|
||||
917500000,
|
||||
926500000,
|
||||
908500000,
|
||||
916000000,
|
||||
905500000,
|
||||
916000000,
|
||||
903000000,
|
||||
905000000,
|
||||
915000000,
|
||||
913000000,
|
||||
907000000,
|
||||
910000000,
|
||||
926500000,
|
||||
925500000,
|
||||
911000000,
|
||||
};
|
||||
|
||||
// Default settings
|
||||
tLoRaSettings LoRaSettings =
|
||||
{
|
||||
LoRa_FREQENCY , // RFFrequency
|
||||
20, // Power
|
||||
9, // SignalBw [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
|
||||
12, // SpreadingFactor [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096 chips]
|
||||
2, // ErrorCoding [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
|
||||
true, // CrcOn [0: OFF, 1: ON]
|
||||
false, // ImplicitHeaderOn [0: OFF, 1: ON]
|
||||
0, // RxSingleOn [0: Continuous, 1 Single]
|
||||
0, // FreqHopOn [0: OFF, 1: ON]
|
||||
4, // HopPeriod Hops every frequency hopping period symbols
|
||||
1000, // TxPacketTimeout
|
||||
1000, // RxPacketTimeout
|
||||
128, // PayloadLength (used for implicit header mode)
|
||||
};
|
||||
|
||||
/*!
|
||||
* SX1276 LoRa registers variable
|
||||
*/
|
||||
tSX1276LR* SX1276LR;
|
||||
|
||||
/*!
|
||||
* Local RF buffer for communication support
|
||||
*/
|
||||
static uint8_t RFBuffer[RF_BUFFER_SIZE];
|
||||
static uint8_t TFBuffer[RF_BUFFER_SIZE];
|
||||
|
||||
/*!
|
||||
* RF state machine variable
|
||||
*/
|
||||
static uint8_t RFLRState = RFLR_STATE_IDLE;
|
||||
|
||||
/*!
|
||||
* Rx management support variables
|
||||
*/
|
||||
static uint16_t RxPacketSize = 0;
|
||||
static int8_t RxPacketSnrEstimate;
|
||||
static double RxPacketRssiValue;
|
||||
static uint8_t RxGain = 1;
|
||||
static uint32_t RxTimeoutTimer = 0;
|
||||
|
||||
/*!
|
||||
* PacketTimeout Stores the Rx window time value for packet reception
|
||||
*/
|
||||
static uint32_t PacketTimeout;
|
||||
|
||||
/*!
|
||||
* Tx management support variables
|
||||
*/
|
||||
static uint16_t TxPacketSize = 0;
|
||||
|
||||
|
||||
void SX1276LoRaInit( void )
|
||||
{
|
||||
RFLRState = RFLR_STATE_IDLE;
|
||||
|
||||
SX1276LoRaSetDefaults();
|
||||
|
||||
SX1276ReadBuffer( REG_LR_OPMODE, SX1276Regs + 1, 0x70 - 1 );
|
||||
|
||||
//SX1276LoRaSetOpMode( RFLR_OPMODE_SLEEP );
|
||||
|
||||
SX1276LR->RegLna = RFLR_LNA_GAIN_G1;
|
||||
SX1276WriteBuffer( REG_LR_OPMODE, SX1276Regs + 1, 0x70 - 1 );
|
||||
|
||||
// set the RF settings
|
||||
SX1276LoRaSetRFFrequency( LoRaSettings.RFFrequency );
|
||||
SX1276LoRaSetSpreadingFactor( LoRaSettings.SpreadingFactor );
|
||||
SX1276LoRaSetErrorCoding( LoRaSettings.ErrorCoding );
|
||||
SX1276LoRaSetPacketCrcOn( LoRaSettings.CrcOn );
|
||||
SX1276LoRaSetSignalBandwidth( LoRaSettings.SignalBw );
|
||||
SX1276LoRaSetImplicitHeaderOn( LoRaSettings.ImplicitHeaderOn );
|
||||
|
||||
SX1276LoRaSetSymbTimeout(0x3FF);
|
||||
SX1276LoRaSetPayloadLength( LoRaSettings.PayloadLength );
|
||||
SX1276LoRaSetLowDatarateOptimize( true );
|
||||
|
||||
#if( ( MODULE_SX1276RF1IAS == 1 ) || ( MODULE_SX1276RF1KAS == 1 ) )
|
||||
if( LoRaSettings.RFFrequency > 860000000 )
|
||||
{
|
||||
SX1276LoRaSetPAOutput( RFLR_PACONFIG_PASELECT_RFO );
|
||||
SX1276LoRaSetPa20dBm( false );
|
||||
LoRaSettings.Power = 14;
|
||||
SX1276LoRaSetRFPower( LoRaSettings.Power );
|
||||
}
|
||||
else
|
||||
{
|
||||
//SX1276Write( REG_LR_OCP, 0x3f );
|
||||
SX1276LoRaSetPAOutput( RFLR_PACONFIG_PASELECT_PABOOST );
|
||||
SX1276LoRaSetPa20dBm( true );
|
||||
LoRaSettings.Power = 20;
|
||||
SX1276LoRaSetRFPower( LoRaSettings.Power );
|
||||
}
|
||||
#elif( MODULE_SX1276RF1JAS == 1 )
|
||||
if( LoRaSettings.RFFrequency > 380000000 )
|
||||
{
|
||||
SX1276LoRaSetPAOutput( RFLR_PACONFIG_PASELECT_PABOOST );
|
||||
SX1276LoRaSetPa20dBm( true );
|
||||
LoRaSettings.Power = 20;
|
||||
SX1276LoRaSetRFPower( LoRaSettings.Power );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276LoRaSetPAOutput( RFLR_PACONFIG_PASELECT_RFO );
|
||||
SX1276LoRaSetPa20dBm( false );
|
||||
LoRaSettings.Power = 14;
|
||||
SX1276LoRaSetRFPower( LoRaSettings.Power );
|
||||
}
|
||||
#endif
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );
|
||||
|
||||
SX1276ReadBuffer( REG_LR_OPMODE, SX1276Regs + 1, 0x70 - 1 );
|
||||
}
|
||||
|
||||
void SX1276LoRaSetDefaults( void )
|
||||
{
|
||||
// REMARK: See SX1276 datasheet for modified default values.
|
||||
|
||||
// Sets IF frequency selection manual
|
||||
SX1276Read( REG_LR_VERSION, &SX1276LR->RegVersion );
|
||||
}
|
||||
|
||||
void SX1276LoRaReset( void )
|
||||
{
|
||||
uint32_t startTick;
|
||||
|
||||
SX1276SetReset( RADIO_RESET_ON );
|
||||
|
||||
// Wait 1ms
|
||||
startTick = GET_TICK_COUNT( );
|
||||
while( ( GET_TICK_COUNT( ) - startTick ) < TICK_RATE_MS( 1 ) );
|
||||
|
||||
SX1276SetReset( RADIO_RESET_OFF );
|
||||
|
||||
// Wait 6ms
|
||||
startTick = GET_TICK_COUNT( );
|
||||
while( ( GET_TICK_COUNT( ) - startTick ) < TICK_RATE_MS( 6 ) );
|
||||
}
|
||||
|
||||
void SX1276LoRaSetOpMode( uint8_t opMode )
|
||||
{
|
||||
static uint8_t opModePrev = RFLR_OPMODE_STANDBY;
|
||||
static bool antennaSwitchTxOnPrev = true;
|
||||
bool antennaSwitchTxOn = false;
|
||||
opModePrev = SX1276LR->RegOpMode & ~RFLR_OPMODE_MASK;
|
||||
if( opMode != opModePrev )
|
||||
{
|
||||
if( opMode == RFLR_OPMODE_TRANSMITTER )
|
||||
{
|
||||
antennaSwitchTxOn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
antennaSwitchTxOn = false;
|
||||
}
|
||||
if( antennaSwitchTxOn != antennaSwitchTxOnPrev )
|
||||
{
|
||||
antennaSwitchTxOnPrev = antennaSwitchTxOn; // Antenna switch control
|
||||
RXTX( antennaSwitchTxOn );
|
||||
}
|
||||
SX1276LR->RegOpMode = ( SX1276LR->RegOpMode & RFLR_OPMODE_MASK ) | opMode | RFLR_OPMODE_FREQMODE_ACCESS_LF;
|
||||
|
||||
SX1276Write( REG_LR_OPMODE, SX1276LR->RegOpMode );
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetOpMode( void )
|
||||
{
|
||||
SX1276Read( REG_LR_OPMODE, &SX1276LR->RegOpMode );
|
||||
|
||||
return SX1276LR->RegOpMode & ~RFLR_OPMODE_MASK;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaReadRxGain( void )
|
||||
{
|
||||
|
||||
SX1276Read( REG_LR_LNA, &SX1276LR->RegLna );
|
||||
return( SX1276LR->RegLna >> 5 ) & 0x07;
|
||||
}
|
||||
|
||||
double SX1276LoRaReadRssi( void )
|
||||
{
|
||||
// Reads the RSSI value
|
||||
SX1276Read( REG_LR_RSSIVALUE, &SX1276LR->RegRssiValue );
|
||||
|
||||
if( LoRaSettings.RFFrequency < 860000000 )
|
||||
{
|
||||
return RssiOffsetLF[LoRaSettings.SignalBw] + ( double )SX1276LR->RegRssiValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RssiOffsetHF[LoRaSettings.SignalBw] + ( double )SX1276LR->RegRssiValue;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetPacketRxGain( void )
|
||||
{
|
||||
return RxGain;
|
||||
}
|
||||
|
||||
int8_t SX1276LoRaGetPacketSnr( void )
|
||||
{
|
||||
return RxPacketSnrEstimate;
|
||||
}
|
||||
|
||||
double SX1276LoRaGetPacketRssi( void )
|
||||
{
|
||||
return RxPacketRssiValue;
|
||||
}
|
||||
|
||||
void SX1276LoRaStartRx( void )
|
||||
{
|
||||
SX1276LoRaSetRFState( RFLR_STATE_RX_INIT );
|
||||
}
|
||||
|
||||
void SX1276LoRaGetRxPacket( void *buffer, uint16_t *size )
|
||||
{
|
||||
*size = RxPacketSize;
|
||||
RxPacketSize = 0;
|
||||
memcpy( (void*)buffer, (void*)RFBuffer, (size_t)*size );
|
||||
}
|
||||
|
||||
void SX1276LoRaSetTxPacket( const void *buffer, uint16_t size )
|
||||
{
|
||||
if( LoRaSettings.FreqHopOn == false )
|
||||
{
|
||||
TxPacketSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxPacketSize = 255;
|
||||
}
|
||||
memcpy( ( void * )TFBuffer, buffer, ( size_t )TxPacketSize );
|
||||
|
||||
RFLRState = RFLR_STATE_TX_INIT;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetRFState( void )
|
||||
{
|
||||
return RFLRState;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetRFState( uint8_t state )
|
||||
{
|
||||
RFLRState = state;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Process the LoRa modem Rx and Tx state machines depending on the
|
||||
* SX1276 operating mode.
|
||||
*
|
||||
* \retval rfState Current RF state [RF_IDLE, RF_BUSY,
|
||||
* RF_RX_DONE, RF_RX_TIMEOUT,
|
||||
* RF_TX_DONE, RF_TX_TIMEOUT]
|
||||
*/
|
||||
uint32_t SX1276LoRaProcess( void )
|
||||
{
|
||||
uint32_t result = RF_BUSY;
|
||||
uint8_t regValue = 0;
|
||||
|
||||
switch( RFLRState )
|
||||
{
|
||||
case RFLR_STATE_IDLE:
|
||||
break;
|
||||
case RFLR_STATE_RX_INIT:
|
||||
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
|
||||
SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |
|
||||
//RFLR_IRQFLAGS_RXDONE |
|
||||
RFLR_IRQFLAGS_PAYLOADCRCERROR |
|
||||
RFLR_IRQFLAGS_VALIDHEADER |
|
||||
RFLR_IRQFLAGS_TXDONE |
|
||||
RFLR_IRQFLAGS_CADDONE |
|
||||
RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
|
||||
RFLR_IRQFLAGS_CADDETECTED;
|
||||
SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );
|
||||
|
||||
if(LoRaSettings.FreqHopOn == true )
|
||||
{
|
||||
SX1276LR->RegHopPeriod = LoRaSettings.HopPeriod;
|
||||
|
||||
SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );
|
||||
SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276LR->RegHopPeriod = 255;
|
||||
}
|
||||
|
||||
SX1276Write( REG_LR_HOPPERIOD, SX1276LR->RegHopPeriod );
|
||||
|
||||
if( LoRaSettings.RxSingleOn == true ) // Rx single mode
|
||||
{
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_RECEIVER_SINGLE );
|
||||
}
|
||||
else // Rx continuous mode
|
||||
{
|
||||
SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxBaseAddr;
|
||||
|
||||
SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_RECEIVER );
|
||||
}
|
||||
memset( RFBuffer, 0, ( size_t )RF_BUFFER_SIZE );
|
||||
Rx_Time_Start=TickCounter;
|
||||
PacketTimeout = LoRaSettings.RxPacketTimeout;
|
||||
RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
RFLRState = RFLR_STATE_RX_RUNNING;
|
||||
break;
|
||||
case RFLR_STATE_RX_RUNNING:
|
||||
SX1276Read(0x12, ®Value);
|
||||
// RxDone
|
||||
if(regValue & (1<<6))
|
||||
{
|
||||
RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
if( LoRaSettings.FreqHopOn == true )
|
||||
{
|
||||
SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );
|
||||
SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );
|
||||
}
|
||||
// Clear Irq
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE );
|
||||
RFLRState = RFLR_STATE_RX_DONE;
|
||||
}
|
||||
// FHSS Changed Channel
|
||||
if(regValue & (1<<1))
|
||||
{
|
||||
RxTimeoutTimer = GET_TICK_COUNT( );
|
||||
if( LoRaSettings.FreqHopOn == true )
|
||||
{
|
||||
SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );
|
||||
SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );
|
||||
}
|
||||
// Clear Irq
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );
|
||||
//RxGain = SX1276LoRaReadRxGain( );
|
||||
}
|
||||
if( LoRaSettings.RxSingleOn == true ) // Rx single mode
|
||||
{
|
||||
if( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout )
|
||||
{
|
||||
RFLRState = RFLR_STATE_RX_TIMEOUT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RFLR_STATE_RX_DONE:
|
||||
SX1276Read( REG_LR_IRQFLAGS, &SX1276LR->RegIrqFlags );
|
||||
if( ( SX1276LR->RegIrqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR ) == RFLR_IRQFLAGS_PAYLOADCRCERROR )
|
||||
{
|
||||
// Clear Irq
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR );
|
||||
if( LoRaSettings.RxSingleOn == true ) // Rx single mode
|
||||
{
|
||||
RFLRState = RFLR_STATE_RX_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
RFLRState = RFLR_STATE_RX_RUNNING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( LoRaSettings.RxSingleOn == true ) // Rx single mode
|
||||
{
|
||||
SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxBaseAddr;
|
||||
SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
|
||||
if( LoRaSettings.ImplicitHeaderOn == true )
|
||||
{
|
||||
RxPacketSize = SX1276LR->RegPayloadLength;
|
||||
SX1276ReadFifo( RFBuffer, SX1276LR->RegPayloadLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276Read( REG_LR_NBRXBYTES, &SX1276LR->RegNbRxBytes );
|
||||
RxPacketSize = SX1276LR->RegNbRxBytes;
|
||||
SX1276ReadFifo( RFBuffer, SX1276LR->RegNbRxBytes );
|
||||
}
|
||||
}
|
||||
else // Rx continuous mode
|
||||
{
|
||||
SX1276Read( REG_LR_FIFORXCURRENTADDR, &SX1276LR->RegFifoRxCurrentAddr );
|
||||
if( LoRaSettings.ImplicitHeaderOn == true )
|
||||
{
|
||||
RxPacketSize = SX1276LR->RegPayloadLength;
|
||||
SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxCurrentAddr;
|
||||
SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
|
||||
SX1276ReadFifo( RFBuffer, SX1276LR->RegPayloadLength );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276Read( REG_LR_NBRXBYTES, &SX1276LR->RegNbRxBytes );
|
||||
RxPacketSize = SX1276LR->RegNbRxBytes;
|
||||
SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxCurrentAddr;
|
||||
SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
|
||||
SX1276ReadFifo( RFBuffer, SX1276LR->RegNbRxBytes );
|
||||
}
|
||||
}
|
||||
if( LoRaSettings.RxSingleOn == true ) // Rx single mode
|
||||
{
|
||||
RFLRState = RFLR_STATE_RX_INIT;
|
||||
}
|
||||
else // Rx continuous mode
|
||||
{
|
||||
RFLRState = RFLR_STATE_RX_RUNNING;
|
||||
}
|
||||
Rx_Time_End=TickCounter;
|
||||
result = RF_RX_DONE;
|
||||
break;
|
||||
case RFLR_STATE_RX_TIMEOUT:
|
||||
RFLRState = RFLR_STATE_RX_INIT;
|
||||
result = RF_RX_TIMEOUT;
|
||||
break;
|
||||
case RFLR_STATE_TX_INIT:
|
||||
Tx_Time_Start = TickCounter;
|
||||
|
||||
// Initializes the payload size
|
||||
SX1276LR->RegPayloadLength = TxPacketSize;
|
||||
SX1276Write( REG_LR_PAYLOADLENGTH, SX1276LR->RegPayloadLength );
|
||||
|
||||
SX1276LR->RegFifoTxBaseAddr = 0x00; // Full buffer used for Tx
|
||||
SX1276Write( REG_LR_FIFOTXBASEADDR, SX1276LR->RegFifoTxBaseAddr );
|
||||
|
||||
SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoTxBaseAddr;
|
||||
SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
|
||||
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );
|
||||
|
||||
// Write payload buffer to LORA modem
|
||||
SX1276WriteFifo( TFBuffer, SX1276LR->RegPayloadLength );
|
||||
|
||||
if( LoRaSettings.FreqHopOn == true )
|
||||
{
|
||||
SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |
|
||||
RFLR_IRQFLAGS_RXDONE |
|
||||
RFLR_IRQFLAGS_PAYLOADCRCERROR |
|
||||
RFLR_IRQFLAGS_VALIDHEADER |
|
||||
//RFLR_IRQFLAGS_TXDONE |
|
||||
RFLR_IRQFLAGS_CADDONE |
|
||||
RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
|
||||
RFLR_IRQFLAGS_CADDETECTED;
|
||||
SX1276LR->RegHopPeriod = LoRaSettings.HopPeriod;
|
||||
SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );
|
||||
SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |
|
||||
RFLR_IRQFLAGS_RXDONE |
|
||||
RFLR_IRQFLAGS_PAYLOADCRCERROR |
|
||||
RFLR_IRQFLAGS_VALIDHEADER |
|
||||
//RFLR_IRQFLAGS_TXDONE |
|
||||
RFLR_IRQFLAGS_CADDONE |
|
||||
RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
|
||||
RFLR_IRQFLAGS_CADDETECTED;
|
||||
SX1276LR->RegHopPeriod = 0;
|
||||
}
|
||||
SX1276Write( REG_LR_HOPPERIOD, SX1276LR->RegHopPeriod );
|
||||
SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );
|
||||
|
||||
SX1276Write( REG_LR_DIOMAPPING1, ( regValue & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 );//DIO0设置为TXdone中断
|
||||
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_TRANSMITTER );
|
||||
|
||||
RFLRState = RFLR_STATE_TX_RUNNING;
|
||||
break;
|
||||
case RFLR_STATE_TX_RUNNING:
|
||||
SX1276Read(0x12, ®Value);
|
||||
if(regValue & (1<<3))
|
||||
{
|
||||
// Clear Irq
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE );
|
||||
RFLRState = RFLR_STATE_TX_DONE;
|
||||
}
|
||||
// FHSS Changed Channel
|
||||
if(regValue & (1<<3))
|
||||
{
|
||||
if( LoRaSettings.FreqHopOn == true )
|
||||
{
|
||||
SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );
|
||||
SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );
|
||||
}
|
||||
// Clear Irq
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );
|
||||
}
|
||||
break;
|
||||
case RFLR_STATE_TX_DONE:
|
||||
Tx_Time_End=TickCounter;
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );
|
||||
RFLRState = RFLR_STATE_IDLE;
|
||||
result = RF_TX_DONE;
|
||||
break;
|
||||
case RFLR_STATE_CAD_INIT:
|
||||
// optimize the power consumption by switching off the transmitter as soon as the packet has been sent
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );
|
||||
SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |
|
||||
RFLR_IRQFLAGS_RXDONE |
|
||||
RFLR_IRQFLAGS_PAYLOADCRCERROR |
|
||||
RFLR_IRQFLAGS_VALIDHEADER |
|
||||
RFLR_IRQFLAGS_TXDONE |
|
||||
//RFLR_IRQFLAGS_CADDONE |
|
||||
RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL;
|
||||
//RFLR_IRQFLAGS_CADDETECTED;
|
||||
SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );
|
||||
|
||||
SX1276LoRaSetOpMode( RFLR_OPMODE_CAD );
|
||||
RFLRState = RFLR_STATE_CAD_RUNNING;
|
||||
|
||||
break;
|
||||
case RFLR_STATE_CAD_RUNNING:
|
||||
SX1276Read(0x12,®Value);
|
||||
int cad_done = regValue & (1<<2);
|
||||
int cad_detected = regValue & (1<<0);
|
||||
|
||||
if( cad_done ) //CAD Done interrupt
|
||||
{
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE );
|
||||
if( cad_detected ) // CAD Detected interrupt
|
||||
{
|
||||
SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED );
|
||||
//CAD detected, we have a LoRa preamble
|
||||
RFLRState = RFLR_STATE_RX_INIT;
|
||||
result = RF_CHANNEL_ACTIVITY_DETECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The device goes in Standby Mode automatically
|
||||
RFLRState = RFLR_STATE_IDLE;
|
||||
result = RF_CHANNEL_EMPTY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t SX1276LoraChannelEmpty( void )
|
||||
{
|
||||
uint32_t result = 0;
|
||||
RFLRState = RFLR_STATE_CAD_INIT;
|
||||
SX1276LoRaProcess();
|
||||
while(RFLRState == RFLR_STATE_CAD_RUNNING)
|
||||
{
|
||||
//KPrintf("\nLora--SX1276LoRaProcess()");
|
||||
result = SX1276LoRaProcess();
|
||||
}
|
||||
|
||||
if(result == RF_CHANNEL_EMPTY)
|
||||
{
|
||||
KPrintf("\nLora--RF_CHANNEL_EMPTY\n");
|
||||
return 0;
|
||||
}
|
||||
else if(result == RF_CHANNEL_ACTIVITY_DETECTED)
|
||||
{
|
||||
KPrintf("\nLora--RF_CHANNEL_ACTIVITY_DETECTED\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_SX1276_RADIO
|
||||
@@ -0,0 +1,820 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Original Copyright (C) SEMTECH S.A.
|
||||
* Modified Copyright (C) 2020 AIIT XUOS Lab
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-LoRa.h
|
||||
* \brief SX1276 RF chip driver mode LoRa
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date Nov 21 2012
|
||||
* \author Miguel Luis
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-LoRa.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#ifndef __SX1276_LORA_H__
|
||||
#define __SX1276_LORA_H__
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
|
||||
//SX1276一些配置参数设置
|
||||
typedef struct sLoRaSettings
|
||||
{
|
||||
uint32_t RFFrequency; //无线通信频率
|
||||
int8_t Power; //功率
|
||||
uint8_t SignalBw; //LORA 带宽[0: 7.8 kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,
|
||||
//5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz, other: Reserved]
|
||||
uint8_t SpreadingFactor; //扩频因子 LORA [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096 chips]
|
||||
uint8_t ErrorCoding; //LORA 纠错码 [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
|
||||
bool CrcOn; //CRC效验开关 [0: OFF, 1: ON]
|
||||
bool ImplicitHeaderOn; //隐藏头部信息开关 [0: OFF, 1: ON]
|
||||
bool RxSingleOn; //接收单次模式\连续模式配置[0: Continuous, 1 Single]
|
||||
bool FreqHopOn; //跳频模式开关 [0: OFF, 1: ON]
|
||||
uint8_t HopPeriod; //跳频之间的周期长度 Hops every frequency hopping period symbols
|
||||
uint32_t TxPacketTimeout; //最大发送时间
|
||||
uint32_t RxPacketTimeout; //最大接收时间
|
||||
uint8_t PayloadLength; //数据长度
|
||||
}tLoRaSettings;
|
||||
|
||||
//RF数据包大小(模块配备了256Byte的RAM缓存,该缓存仅能通过LoRa模式访问)
|
||||
#define RF_BUFFER_SIZE_MAX 256
|
||||
#define RF_BUFFER_SIZE 256
|
||||
|
||||
|
||||
//LoRa的返回值
|
||||
typedef enum
|
||||
{
|
||||
RFLR_STATE_IDLE,
|
||||
RFLR_STATE_RX_INIT,
|
||||
RFLR_STATE_RX_RUNNING,
|
||||
RFLR_STATE_RX_DONE,
|
||||
RFLR_STATE_RX_TIMEOUT,
|
||||
RFLR_STATE_TX_INIT,
|
||||
RFLR_STATE_TX_RUNNING,
|
||||
RFLR_STATE_TX_DONE,
|
||||
RFLR_STATE_TX_TIMEOUT,
|
||||
RFLR_STATE_CAD_INIT,
|
||||
RFLR_STATE_CAD_RUNNING,
|
||||
}tRFLRStates;
|
||||
|
||||
|
||||
//SX1276 definitions
|
||||
#define XTAL_FREQ 32000000
|
||||
#define FREQ_STEP 61.03515625
|
||||
|
||||
/*LoRa模式寄存器映射*/
|
||||
//SX1276内部寄存器地址
|
||||
#define REG_LR_FIFO 0x00 //FIFO 数据输入/输出。当器件处于睡眠模式时,FIFO被清零,无法访问。
|
||||
|
||||
//通用寄存器
|
||||
#define REG_LR_OPMODE 0x01 //关于模式选择相关的寄存器
|
||||
#define REG_LR_BANDSETTING 0x04
|
||||
#define REG_LR_FRFMSB 0x06 //RF 载波频率最高有效位
|
||||
#define REG_LR_FRFMID 0x07 //RF 载波频率中间有效位
|
||||
#define REG_LR_FRFLSB 0x08 //RF 载波频率最低有效位
|
||||
|
||||
//RF模块寄存器
|
||||
#define REG_LR_PACONFIG 0x09
|
||||
#define REG_LR_PARAMP 0x0A
|
||||
#define REG_LR_OCP 0x0B
|
||||
#define REG_LR_LNA 0x0C
|
||||
|
||||
//LoRa页面寄存器
|
||||
#define REG_LR_FIFOADDRPTR 0x0D
|
||||
#define REG_LR_FIFOTXBASEADDR 0x0E
|
||||
#define REG_LR_FIFORXBASEADDR 0x0F
|
||||
#define REG_LR_FIFORXCURRENTADDR 0x10
|
||||
#define REG_LR_IRQFLAGSMASK 0x11 //IAQ标志屏蔽
|
||||
#define REG_LR_IRQFLAGS 0x12
|
||||
#define REG_LR_NBRXBYTES 0x13
|
||||
#define REG_LR_RXHEADERCNTVALUEMSB 0x14
|
||||
#define REG_LR_RXHEADERCNTVALUELSB 0x15
|
||||
#define REG_LR_RXPACKETCNTVALUEMSB 0x16
|
||||
#define REG_LR_RXPACKETCNTVALUELSB 0x17
|
||||
#define REG_LR_MODEMSTAT 0x18
|
||||
#define REG_LR_PKTSNRVALUE 0x19
|
||||
#define REG_LR_PKTRSSIVALUE 0x1A
|
||||
#define REG_LR_RSSIVALUE 0x1B
|
||||
#define REG_LR_HOPCHANNEL 0x1C
|
||||
#define REG_LR_MODEMCONFIG1 0x1D
|
||||
#define REG_LR_MODEMCONFIG2 0x1E
|
||||
#define REG_LR_SYMBTIMEOUTLSB 0x1F
|
||||
#define REG_LR_PREAMBLEMSB 0x20
|
||||
#define REG_LR_PREAMBLELSB 0x21
|
||||
#define REG_LR_PAYLOADLENGTH 0x22
|
||||
#define REG_LR_PAYLOADMAXLENGTH 0x23
|
||||
#define REG_LR_HOPPERIOD 0x24
|
||||
#define REG_LR_FIFORXBYTEADDR 0x25
|
||||
#define REG_LR_MODEMCONFIG3 0x26
|
||||
/*以上是LoRa模式寄存器映射*/
|
||||
|
||||
//IO控制寄存器(关于DI00-DI05的映射设置)
|
||||
#define REG_LR_DIOMAPPING1 0x40
|
||||
#define REG_LR_DIOMAPPING2 0x41
|
||||
|
||||
//版本寄存器
|
||||
#define REG_LR_VERSION 0x42
|
||||
|
||||
//附加寄存器
|
||||
#define REG_LR_PLLHOP 0x44
|
||||
#define REG_LR_TCXO 0x4B
|
||||
#define REG_LR_PADAC 0x4D
|
||||
#define REG_LR_FORMERTEMP 0x5B
|
||||
#define REG_LR_BITRATEFRAC 0x5D
|
||||
#define REG_LR_AGCREF 0x61
|
||||
#define REG_LR_AGCTHRESH1 0x62
|
||||
#define REG_LR_AGCTHRESH2 0x63
|
||||
#define REG_LR_AGCTHRESH3 0x64
|
||||
|
||||
//与模式选择相关的宏定义 RegOpMode(寄存器地址0X01)
|
||||
#define RFLR_OPMODE_LONGRANGEMODE_MASK 0x7F
|
||||
#define RFLR_OPMODE_LONGRANGEMODE_OFF 0x00 // Default
|
||||
#define RFLR_OPMODE_LONGRANGEMODE_ON 0x80
|
||||
|
||||
#define RFLR_OPMODE_ACCESSSHAREDREG_MASK 0xBF
|
||||
#define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE 0x40
|
||||
#define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE 0x00 // Default
|
||||
|
||||
#define RFLR_OPMODE_FREQMODE_ACCESS_MASK 0xF7
|
||||
#define RFLR_OPMODE_FREQMODE_ACCESS_LF 0x08 // Default
|
||||
#define RFLR_OPMODE_FREQMODE_ACCESS_HF 0x00
|
||||
|
||||
#define RFLR_OPMODE_MASK 0xF8
|
||||
#define RFLR_OPMODE_SLEEP 0x00 //睡眠模式
|
||||
#define RFLR_OPMODE_STANDBY 0x01 //待机模式
|
||||
#define RFLR_OPMODE_SYNTHESIZER_TX 0x02 //频率合成器转换至Tx频率
|
||||
#define RFLR_OPMODE_TRANSMITTER 0x03 //发送模式
|
||||
#define RFLR_OPMODE_SYNTHESIZER_RX 0x04 //频率合成器转换至Rx频率
|
||||
#define RFLR_OPMODE_RECEIVER 0x05 //接收模式
|
||||
|
||||
#define RFLR_OPMODE_RECEIVER_SINGLE 0x06 //单次接收模式
|
||||
#define RFLR_OPMODE_CAD 0x07 //CAD模式
|
||||
|
||||
//与位带操作相关的宏定义
|
||||
#define RFLR_BANDSETTING_MASK 0x3F
|
||||
#define RFLR_BANDSETTING_AUTO 0x00 // Default
|
||||
#define RFLR_BANDSETTING_DIV_BY_1 0x40
|
||||
#define RFLR_BANDSETTING_DIV_BY_2 0x80
|
||||
#define RFLR_BANDSETTING_DIV_BY_6 0xC0
|
||||
|
||||
//射频载波频率设置相关宏定义 RegFrf (MHz)(寄存器地址0x06,0x07,0x08)
|
||||
#define RFLR_FRFMSB_434_MHZ 0x6C // Default
|
||||
#define RFLR_FRFMID_434_MHZ 0x80 // Default
|
||||
#define RFLR_FRFLSB_434_MHZ 0x00 // Default
|
||||
|
||||
#define RFLR_FRFMSB_470_MHZ 0x73 // Default
|
||||
#define RFLR_FRFMID_470_MHZ 0xBB // Default
|
||||
#define RFLR_FRFLSB_470_MHZ 0xBB // Default
|
||||
|
||||
#define RFLR_FRFMSB_863_MHZ 0xD7
|
||||
#define RFLR_FRFMID_863_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_863_MHZ 0x00
|
||||
#define RFLR_FRFMSB_864_MHZ 0xD8
|
||||
#define RFLR_FRFMID_864_MHZ 0x00
|
||||
#define RFLR_FRFLSB_864_MHZ 0x00
|
||||
#define RFLR_FRFMSB_865_MHZ 0xD8
|
||||
#define RFLR_FRFMID_865_MHZ 0x40
|
||||
#define RFLR_FRFLSB_865_MHZ 0x00
|
||||
#define RFLR_FRFMSB_866_MHZ 0xD8
|
||||
#define RFLR_FRFMID_866_MHZ 0x80
|
||||
#define RFLR_FRFLSB_866_MHZ 0x00
|
||||
#define RFLR_FRFMSB_867_MHZ 0xD8
|
||||
#define RFLR_FRFMID_867_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_867_MHZ 0x00
|
||||
#define RFLR_FRFMSB_868_MHZ 0xD9
|
||||
#define RFLR_FRFMID_868_MHZ 0x00
|
||||
#define RFLR_FRFLSB_868_MHZ 0x00
|
||||
#define RFLR_FRFMSB_869_MHZ 0xD9
|
||||
#define RFLR_FRFMID_869_MHZ 0x40
|
||||
#define RFLR_FRFLSB_869_MHZ 0x00
|
||||
#define RFLR_FRFMSB_870_MHZ 0xD9
|
||||
#define RFLR_FRFMID_870_MHZ 0x80
|
||||
#define RFLR_FRFLSB_870_MHZ 0x00
|
||||
|
||||
#define RFLR_FRFMSB_902_MHZ 0xE1
|
||||
#define RFLR_FRFMID_902_MHZ 0x80
|
||||
#define RFLR_FRFLSB_902_MHZ 0x00
|
||||
#define RFLR_FRFMSB_903_MHZ 0xE1
|
||||
#define RFLR_FRFMID_903_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_903_MHZ 0x00
|
||||
#define RFLR_FRFMSB_904_MHZ 0xE2
|
||||
#define RFLR_FRFMID_904_MHZ 0x00
|
||||
#define RFLR_FRFLSB_904_MHZ 0x00
|
||||
#define RFLR_FRFMSB_905_MHZ 0xE2
|
||||
#define RFLR_FRFMID_905_MHZ 0x40
|
||||
#define RFLR_FRFLSB_905_MHZ 0x00
|
||||
#define RFLR_FRFMSB_906_MHZ 0xE2
|
||||
#define RFLR_FRFMID_906_MHZ 0x80
|
||||
#define RFLR_FRFLSB_906_MHZ 0x00
|
||||
#define RFLR_FRFMSB_907_MHZ 0xE2
|
||||
#define RFLR_FRFMID_907_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_907_MHZ 0x00
|
||||
#define RFLR_FRFMSB_908_MHZ 0xE3
|
||||
#define RFLR_FRFMID_908_MHZ 0x00
|
||||
#define RFLR_FRFLSB_908_MHZ 0x00
|
||||
#define RFLR_FRFMSB_909_MHZ 0xE3
|
||||
#define RFLR_FRFMID_909_MHZ 0x40
|
||||
#define RFLR_FRFLSB_909_MHZ 0x00
|
||||
#define RFLR_FRFMSB_910_MHZ 0xE3
|
||||
#define RFLR_FRFMID_910_MHZ 0x80
|
||||
#define RFLR_FRFLSB_910_MHZ 0x00
|
||||
#define RFLR_FRFMSB_911_MHZ 0xE3
|
||||
#define RFLR_FRFMID_911_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_911_MHZ 0x00
|
||||
#define RFLR_FRFMSB_912_MHZ 0xE4
|
||||
#define RFLR_FRFMID_912_MHZ 0x00
|
||||
#define RFLR_FRFLSB_912_MHZ 0x00
|
||||
#define RFLR_FRFMSB_913_MHZ 0xE4
|
||||
#define RFLR_FRFMID_913_MHZ 0x40
|
||||
#define RFLR_FRFLSB_913_MHZ 0x00
|
||||
#define RFLR_FRFMSB_914_MHZ 0xE4
|
||||
#define RFLR_FRFMID_914_MHZ 0x80
|
||||
#define RFLR_FRFLSB_914_MHZ 0x00
|
||||
#define RFLR_FRFMSB_915_MHZ 0xE4 // Default
|
||||
#define RFLR_FRFMID_915_MHZ 0xC0 // Default
|
||||
#define RFLR_FRFLSB_915_MHZ 0x00 // Default
|
||||
#define RFLR_FRFMSB_916_MHZ 0xE5
|
||||
#define RFLR_FRFMID_916_MHZ 0x00
|
||||
#define RFLR_FRFLSB_916_MHZ 0x00
|
||||
#define RFLR_FRFMSB_917_MHZ 0xE5
|
||||
#define RFLR_FRFMID_917_MHZ 0x40
|
||||
#define RFLR_FRFLSB_917_MHZ 0x00
|
||||
#define RFLR_FRFMSB_918_MHZ 0xE5
|
||||
#define RFLR_FRFMID_918_MHZ 0x80
|
||||
#define RFLR_FRFLSB_918_MHZ 0x00
|
||||
#define RFLR_FRFMSB_919_MHZ 0xE5
|
||||
#define RFLR_FRFMID_919_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_919_MHZ 0x00
|
||||
#define RFLR_FRFMSB_920_MHZ 0xE6
|
||||
#define RFLR_FRFMID_920_MHZ 0x00
|
||||
#define RFLR_FRFLSB_920_MHZ 0x00
|
||||
#define RFLR_FRFMSB_921_MHZ 0xE6
|
||||
#define RFLR_FRFMID_921_MHZ 0x40
|
||||
#define RFLR_FRFLSB_921_MHZ 0x00
|
||||
#define RFLR_FRFMSB_922_MHZ 0xE6
|
||||
#define RFLR_FRFMID_922_MHZ 0x80
|
||||
#define RFLR_FRFLSB_922_MHZ 0x00
|
||||
#define RFLR_FRFMSB_923_MHZ 0xE6
|
||||
#define RFLR_FRFMID_923_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_923_MHZ 0x00
|
||||
#define RFLR_FRFMSB_924_MHZ 0xE7
|
||||
#define RFLR_FRFMID_924_MHZ 0x00
|
||||
#define RFLR_FRFLSB_924_MHZ 0x00
|
||||
#define RFLR_FRFMSB_925_MHZ 0xE7
|
||||
#define RFLR_FRFMID_925_MHZ 0x40
|
||||
#define RFLR_FRFLSB_925_MHZ 0x00
|
||||
#define RFLR_FRFMSB_926_MHZ 0xE7
|
||||
#define RFLR_FRFMID_926_MHZ 0x80
|
||||
#define RFLR_FRFLSB_926_MHZ 0x00
|
||||
#define RFLR_FRFMSB_927_MHZ 0xE7
|
||||
#define RFLR_FRFMID_927_MHZ 0xC0
|
||||
#define RFLR_FRFLSB_927_MHZ 0x00
|
||||
#define RFLR_FRFMSB_928_MHZ 0xE8
|
||||
#define RFLR_FRFMID_928_MHZ 0x00
|
||||
#define RFLR_FRFLSB_928_MHZ 0x00
|
||||
|
||||
//PA(功率放大器) 选择和输出功率控制设置相关宏定义 RegPaConfig(寄存器地址0X09)
|
||||
#define RFLR_PACONFIG_PASELECT_MASK 0x7F
|
||||
#define RFLR_PACONFIG_PASELECT_PABOOST 0x80
|
||||
#define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default
|
||||
|
||||
#define RFLR_PACONFIG_MAX_POWER_MASK 0x8F
|
||||
|
||||
#define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0
|
||||
|
||||
//PA(功率放大器) 斜升/斜降时间和低相噪设置相关定义 RegPaRamp(寄存器地址0X0A)
|
||||
#define RFLR_PARAMP_TXBANDFORCE_MASK 0xEF
|
||||
#define RFLR_PARAMP_TXBANDFORCE_BAND_SEL 0x10
|
||||
#define RFLR_PARAMP_TXBANDFORCE_AUTO 0x00 // Default
|
||||
|
||||
#define RFLR_PARAMP_MASK 0xF0
|
||||
#define RFLR_PARAMP_3400_US 0x00
|
||||
#define RFLR_PARAMP_2000_US 0x01
|
||||
#define RFLR_PARAMP_1000_US 0x02
|
||||
#define RFLR_PARAMP_0500_US 0x03
|
||||
#define RFLR_PARAMP_0250_US 0x04
|
||||
#define RFLR_PARAMP_0125_US 0x05
|
||||
#define RFLR_PARAMP_0100_US 0x06
|
||||
#define RFLR_PARAMP_0062_US 0x07
|
||||
#define RFLR_PARAMP_0050_US 0x08
|
||||
#define RFLR_PARAMP_0040_US 0x09 // Default
|
||||
#define RFLR_PARAMP_0031_US 0x0A
|
||||
#define RFLR_PARAMP_0025_US 0x0B
|
||||
#define RFLR_PARAMP_0020_US 0x0C
|
||||
#define RFLR_PARAMP_0015_US 0x0D
|
||||
#define RFLR_PARAMP_0012_US 0x0E
|
||||
#define RFLR_PARAMP_0010_US 0x0F
|
||||
|
||||
//过流保护控制设置相关宏定义 RegOcp(寄存器地址0X0B)
|
||||
#define RFLR_OCP_MASK 0xDF
|
||||
#define RFLR_OCP_ON 0x20 // Default
|
||||
#define RFLR_OCP_OFF 0x00
|
||||
|
||||
#define RFLR_OCP_TRIM_MASK 0xE0
|
||||
#define RFLR_OCP_TRIM_045_MA 0x00
|
||||
#define RFLR_OCP_TRIM_050_MA 0x01
|
||||
#define RFLR_OCP_TRIM_055_MA 0x02
|
||||
#define RFLR_OCP_TRIM_060_MA 0x03
|
||||
#define RFLR_OCP_TRIM_065_MA 0x04
|
||||
#define RFLR_OCP_TRIM_070_MA 0x05
|
||||
#define RFLR_OCP_TRIM_075_MA 0x06
|
||||
#define RFLR_OCP_TRIM_080_MA 0x07
|
||||
#define RFLR_OCP_TRIM_085_MA 0x08
|
||||
#define RFLR_OCP_TRIM_090_MA 0x09
|
||||
#define RFLR_OCP_TRIM_095_MA 0x0A
|
||||
#define RFLR_OCP_TRIM_100_MA 0x0B // Default
|
||||
#define RFLR_OCP_TRIM_105_MA 0x0C
|
||||
#define RFLR_OCP_TRIM_110_MA 0x0D
|
||||
#define RFLR_OCP_TRIM_115_MA 0x0E
|
||||
#define RFLR_OCP_TRIM_120_MA 0x0F
|
||||
#define RFLR_OCP_TRIM_130_MA 0x10
|
||||
#define RFLR_OCP_TRIM_140_MA 0x11
|
||||
#define RFLR_OCP_TRIM_150_MA 0x12
|
||||
#define RFLR_OCP_TRIM_160_MA 0x13
|
||||
#define RFLR_OCP_TRIM_170_MA 0x14
|
||||
#define RFLR_OCP_TRIM_180_MA 0x15
|
||||
#define RFLR_OCP_TRIM_190_MA 0x16
|
||||
#define RFLR_OCP_TRIM_200_MA 0x17
|
||||
#define RFLR_OCP_TRIM_210_MA 0x18
|
||||
#define RFLR_OCP_TRIM_220_MA 0x19
|
||||
#define RFLR_OCP_TRIM_230_MA 0x1A
|
||||
#define RFLR_OCP_TRIM_240_MA 0x1B
|
||||
|
||||
//LNA(低噪声放大器 )设置相关宏定义 RegLna(寄存器地址0X0C)
|
||||
#define RFLR_LNA_GAIN_MASK 0x1F
|
||||
#define RFLR_LNA_GAIN_G1 0x20 // Default
|
||||
#define RFLR_LNA_GAIN_G2 0x40
|
||||
#define RFLR_LNA_GAIN_G3 0x60
|
||||
#define RFLR_LNA_GAIN_G4 0x80
|
||||
#define RFLR_LNA_GAIN_G5 0xA0
|
||||
#define RFLR_LNA_GAIN_G6 0xC0
|
||||
|
||||
#define RFLR_LNA_BOOST_LF_MASK 0xE7
|
||||
#define RFLR_LNA_BOOST_LF_DEFAULT 0x00 // Default
|
||||
#define RFLR_LNA_BOOST_LF_GAIN 0x08
|
||||
#define RFLR_LNA_BOOST_LF_IP3 0x10
|
||||
#define RFLR_LNA_BOOST_LF_BOOST 0x18
|
||||
|
||||
#define RFLR_LNA_RXBANDFORCE_MASK 0xFB
|
||||
#define RFLR_LNA_RXBANDFORCE_BAND_SEL 0x04
|
||||
#define RFLR_LNA_RXBANDFORCE_AUTO 0x00 // Default
|
||||
|
||||
#define RFLR_LNA_BOOST_HF_MASK 0xFC
|
||||
#define RFLR_LNA_BOOST_HF_OFF 0x00 // Default
|
||||
#define RFLR_LNA_BOOST_HF_ON 0x03
|
||||
|
||||
|
||||
//FIFO 数据缓冲区中 SPI 接口地址指针(寄存器地址0X0D)
|
||||
#define RFLR_FIFOADDRPTR 0x00 // Default
|
||||
|
||||
//发送信息的起始位置
|
||||
#define RFLR_FIFOTXBASEADDR 0x80 // Default
|
||||
|
||||
//接收信息的起始位置
|
||||
#define RFLR_FIFORXBASEADDR 0x00 // Default
|
||||
|
||||
/*!
|
||||
* RegFifoRxCurrentAddr (Read Only)
|
||||
*/
|
||||
|
||||
//关于中断屏蔽相关的宏定义
|
||||
#define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80
|
||||
#define RFLR_IRQFLAGS_RXDONE_MASK 0x40
|
||||
#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20
|
||||
#define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10
|
||||
#define RFLR_IRQFLAGS_TXDONE_MASK 0x08
|
||||
#define RFLR_IRQFLAGS_CADDONE_MASK 0x04
|
||||
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02
|
||||
#define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01
|
||||
|
||||
//关于中断打开相关的宏定义
|
||||
#define RFLR_IRQFLAGS_RXTIMEOUT 0x80
|
||||
#define RFLR_IRQFLAGS_RXDONE 0x40
|
||||
#define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20
|
||||
#define RFLR_IRQFLAGS_VALIDHEADER 0x10
|
||||
#define RFLR_IRQFLAGS_TXDONE 0x08
|
||||
#define RFLR_IRQFLAGS_CADDONE 0x04
|
||||
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02
|
||||
#define RFLR_IRQFLAGS_CADDETECTED 0x01
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* RegFifoRxNbBytes (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegRxHeaderCntValueMsb (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegRxHeaderCntValueLsb (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegRxPacketCntValueMsb (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegRxPacketCntValueLsb (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegModemStat (Read Only) //
|
||||
*/
|
||||
#define RFLR_MODEMSTAT_RX_CR_MASK 0x1F
|
||||
#define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0
|
||||
|
||||
/*!
|
||||
* RegPktSnrValue (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegPktRssiValue (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* RegRssiValue (Read Only) //
|
||||
*/
|
||||
|
||||
|
||||
//与信号宽度,纠错编码率,是否显示报头有关宏定义(寄存器位置0X1D)
|
||||
#define RFLR_MODEMCONFIG1_BW_MASK 0x0F
|
||||
|
||||
#define RFLR_MODEMCONFIG1_BW_7_81_KHZ 0x00
|
||||
#define RFLR_MODEMCONFIG1_BW_10_41_KHZ 0x10
|
||||
#define RFLR_MODEMCONFIG1_BW_15_62_KHZ 0x20
|
||||
#define RFLR_MODEMCONFIG1_BW_20_83_KHZ 0x30
|
||||
#define RFLR_MODEMCONFIG1_BW_31_25_KHZ 0x40
|
||||
#define RFLR_MODEMCONFIG1_BW_41_66_KHZ 0x50
|
||||
#define RFLR_MODEMCONFIG1_BW_62_50_KHZ 0x60
|
||||
#define RFLR_MODEMCONFIG1_BW_125_KHZ 0x70 // Default
|
||||
#define RFLR_MODEMCONFIG1_BW_250_KHZ 0x80
|
||||
#define RFLR_MODEMCONFIG1_BW_500_KHZ 0x90
|
||||
|
||||
#define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xF1
|
||||
#define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x02
|
||||
#define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x04 // Default
|
||||
#define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x06
|
||||
#define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x08
|
||||
|
||||
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFE
|
||||
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x01
|
||||
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x00 // Default
|
||||
|
||||
//与扩频因子,接收模式,发送CRC开启,RX超时相关宏定义
|
||||
#define RFLR_MODEMCONFIG2_SF_MASK 0x0F
|
||||
#define RFLR_MODEMCONFIG2_SF_6 0x60
|
||||
#define RFLR_MODEMCONFIG2_SF_7 0x70 // Default
|
||||
#define RFLR_MODEMCONFIG2_SF_8 0x80
|
||||
#define RFLR_MODEMCONFIG2_SF_9 0x90
|
||||
#define RFLR_MODEMCONFIG2_SF_10 0xA0
|
||||
#define RFLR_MODEMCONFIG2_SF_11 0xB0
|
||||
#define RFLR_MODEMCONFIG2_SF_12 0xC0
|
||||
|
||||
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7
|
||||
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08
|
||||
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00
|
||||
|
||||
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK 0xFB
|
||||
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_ON 0x04
|
||||
#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_OFF 0x00 // Default
|
||||
|
||||
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC
|
||||
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default
|
||||
|
||||
|
||||
/*!
|
||||
* RegHopChannel (Read Only)
|
||||
*/
|
||||
#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F
|
||||
#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80
|
||||
#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default
|
||||
|
||||
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_MASK 0xBF
|
||||
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_ON 0x40
|
||||
#define RFLR_HOPCHANNEL_PAYLOAD_CRC16_OFF 0x00 // Default
|
||||
|
||||
#define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F
|
||||
|
||||
|
||||
/*!
|
||||
* RegSymbTimeoutLsb
|
||||
*/
|
||||
#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default
|
||||
|
||||
/*!
|
||||
* RegPreambleLengthMsb
|
||||
*/
|
||||
#define RFLR_PREAMBLELENGTHMSB 0x00 // Default
|
||||
|
||||
/*!
|
||||
* RegPreambleLengthLsb
|
||||
*/
|
||||
#define RFLR_PREAMBLELENGTHLSB 0x08 // Default
|
||||
|
||||
/*!
|
||||
* RegPayloadLength
|
||||
*/
|
||||
#define RFLR_PAYLOADLENGTH 0x0E // Default
|
||||
|
||||
/*!
|
||||
* RegPayloadMaxLength
|
||||
*/
|
||||
#define RFLR_PAYLOADMAXLENGTH 0xFF // Default
|
||||
|
||||
/*!
|
||||
* RegHopPeriod
|
||||
*/
|
||||
#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default
|
||||
|
||||
|
||||
/*!
|
||||
* RegDioMapping1
|
||||
*/
|
||||
#define RFLR_DIOMAPPING1_DIO0_MASK 0x3F
|
||||
#define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING1_DIO0_01 0x40
|
||||
#define RFLR_DIOMAPPING1_DIO0_10 0x80
|
||||
#define RFLR_DIOMAPPING1_DIO0_11 0xC0
|
||||
|
||||
#define RFLR_DIOMAPPING1_DIO1_MASK 0xCF
|
||||
#define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING1_DIO1_01 0x10
|
||||
#define RFLR_DIOMAPPING1_DIO1_10 0x20
|
||||
#define RFLR_DIOMAPPING1_DIO1_11 0x30
|
||||
|
||||
#define RFLR_DIOMAPPING1_DIO2_MASK 0xF3
|
||||
#define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING1_DIO2_01 0x04
|
||||
#define RFLR_DIOMAPPING1_DIO2_10 0x08
|
||||
#define RFLR_DIOMAPPING1_DIO2_11 0x0C
|
||||
|
||||
#define RFLR_DIOMAPPING1_DIO3_MASK 0xFC
|
||||
#define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING1_DIO3_01 0x01
|
||||
#define RFLR_DIOMAPPING1_DIO3_10 0x02
|
||||
#define RFLR_DIOMAPPING1_DIO3_11 0x03
|
||||
|
||||
/*!
|
||||
* RegDioMapping2
|
||||
*/
|
||||
#define RFLR_DIOMAPPING2_DIO4_MASK 0x3F
|
||||
#define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING2_DIO4_01 0x40
|
||||
#define RFLR_DIOMAPPING2_DIO4_10 0x80
|
||||
#define RFLR_DIOMAPPING2_DIO4_11 0xC0
|
||||
|
||||
#define RFLR_DIOMAPPING2_DIO5_MASK 0xCF
|
||||
#define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default
|
||||
#define RFLR_DIOMAPPING2_DIO5_01 0x10
|
||||
#define RFLR_DIOMAPPING2_DIO5_10 0x20
|
||||
#define RFLR_DIOMAPPING2_DIO5_11 0x30
|
||||
|
||||
#define RFLR_DIOMAPPING2_MAP_MASK 0xFE
|
||||
#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01
|
||||
#define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default
|
||||
|
||||
/*!
|
||||
* RegVersion (Read Only)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegAgcRef
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegAgcThresh1
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegAgcThresh2
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegAgcThresh3
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegFifoRxByteAddr (Read Only)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* RegPllHop
|
||||
*/
|
||||
#define RFLR_PLLHOP_FASTHOP_MASK 0x7F
|
||||
#define RFLR_PLLHOP_FASTHOP_ON 0x80
|
||||
#define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default
|
||||
|
||||
/*!
|
||||
* RegTcxo
|
||||
*/
|
||||
#define RFLR_TCXO_TCXOINPUT_MASK 0xEF
|
||||
#define RFLR_TCXO_TCXOINPUT_ON 0x10
|
||||
#define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default
|
||||
|
||||
/*!
|
||||
* RegPaDac
|
||||
*/
|
||||
#define RFLR_PADAC_20DBM_MASK 0xF8
|
||||
#define RFLR_PADAC_20DBM_ON 0x07
|
||||
#define RFLR_PADAC_20DBM_OFF 0x04 // Default
|
||||
|
||||
/*!
|
||||
* RegPll
|
||||
*/
|
||||
#define RFLR_PLL_BANDWIDTH_MASK 0x3F
|
||||
#define RFLR_PLL_BANDWIDTH_75 0x00
|
||||
#define RFLR_PLL_BANDWIDTH_150 0x40
|
||||
#define RFLR_PLL_BANDWIDTH_225 0x80
|
||||
#define RFLR_PLL_BANDWIDTH_300 0xC0 // Default
|
||||
|
||||
/*!
|
||||
* RegPllLowPn
|
||||
*/
|
||||
#define RFLR_PLLLOWPN_BANDWIDTH_MASK 0x3F
|
||||
#define RFLR_PLLLOWPN_BANDWIDTH_75 0x00
|
||||
#define RFLR_PLLLOWPN_BANDWIDTH_150 0x40
|
||||
#define RFLR_PLLLOWPN_BANDWIDTH_225 0x80
|
||||
#define RFLR_PLLLOWPN_BANDWIDTH_300 0xC0 // Default
|
||||
|
||||
/*!
|
||||
* RegModemConfig3
|
||||
*/
|
||||
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK 0xF7
|
||||
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON 0x08
|
||||
#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_OFF 0x00 // Default
|
||||
|
||||
#define RFLR_MODEMCONFIG3_AGCAUTO_MASK 0xFB
|
||||
#define RFLR_MODEMCONFIG3_AGCAUTO_ON 0x04 // Default
|
||||
#define RFLR_MODEMCONFIG3_AGCAUTO_OFF 0x00
|
||||
|
||||
/*!
|
||||
* RegFormerTemp
|
||||
*/
|
||||
|
||||
typedef struct sSX1276LR
|
||||
{
|
||||
uint8_t RegFifo; // 0x00
|
||||
// Common settings
|
||||
uint8_t RegOpMode; // 0x01
|
||||
uint8_t RegRes02; // 0x02
|
||||
uint8_t RegRes03; // 0x03
|
||||
uint8_t RegBandSetting; // 0x04
|
||||
uint8_t RegRes05; // 0x05
|
||||
uint8_t RegFrfMsb; // 0x06
|
||||
uint8_t RegFrfMid; // 0x07
|
||||
uint8_t RegFrfLsb; // 0x08
|
||||
// Tx settings
|
||||
uint8_t RegPaConfig; // 0x09
|
||||
uint8_t RegPaRamp; // 0x0A
|
||||
uint8_t RegOcp; // 0x0B
|
||||
// Rx settings
|
||||
uint8_t RegLna; // 0x0C
|
||||
// LoRa registers
|
||||
uint8_t RegFifoAddrPtr; // 0x0D
|
||||
uint8_t RegFifoTxBaseAddr; // 0x0E
|
||||
uint8_t RegFifoRxBaseAddr; // 0x0F
|
||||
uint8_t RegFifoRxCurrentAddr; // 0x10
|
||||
uint8_t RegIrqFlagsMask; // 0x11
|
||||
uint8_t RegIrqFlags; // 0x12
|
||||
uint8_t RegNbRxBytes; // 0x13
|
||||
uint8_t RegRxHeaderCntValueMsb; // 0x14
|
||||
uint8_t RegRxHeaderCntValueLsb; // 0x15
|
||||
uint8_t RegRxPacketCntValueMsb; // 0x16
|
||||
uint8_t RegRxPacketCntValueLsb; // 0x17
|
||||
uint8_t RegModemStat; // 0x18
|
||||
uint8_t RegPktSnrValue; // 0x19
|
||||
uint8_t RegPktRssiValue; // 0x1A
|
||||
uint8_t RegRssiValue; // 0x1B
|
||||
uint8_t RegHopChannel; // 0x1C
|
||||
uint8_t RegModemConfig1; // 0x1D
|
||||
uint8_t RegModemConfig2; // 0x1E
|
||||
uint8_t RegSymbTimeoutLsb; // 0x1F
|
||||
uint8_t RegPreambleMsb; // 0x20
|
||||
uint8_t RegPreambleLsb; // 0x21
|
||||
uint8_t RegPayloadLength; // 0x22
|
||||
uint8_t RegMaxPayloadLength; // 0x23
|
||||
uint8_t RegHopPeriod; // 0x24 跳频周期
|
||||
uint8_t RegFifoRxByteAddr; // 0x25
|
||||
uint8_t RegModemConfig3; // 0x26
|
||||
uint8_t RegTestReserved27[0x30 - 0x27]; // 0x27-0x30
|
||||
uint8_t RegTestReserved31; // 0x31
|
||||
uint8_t RegTestReserved32[0x40 - 0x32]; // 0x32-0x40
|
||||
// I/O settings
|
||||
uint8_t RegDioMapping1; // 0x40
|
||||
uint8_t RegDioMapping2; // 0x41
|
||||
// Version
|
||||
uint8_t RegVersion; // 0x42
|
||||
// Additional settings
|
||||
uint8_t RegAgcRef; // 0x43
|
||||
uint8_t RegAgcThresh1; // 0x44
|
||||
uint8_t RegAgcThresh2; // 0x45
|
||||
uint8_t RegAgcThresh3; // 0x46
|
||||
// Test
|
||||
uint8_t RegTestReserved47[0x4B - 0x47]; // 0x47-0x4A
|
||||
// Additional settings
|
||||
uint8_t RegPllHop; // 0x4B
|
||||
uint8_t RegTestReserved4C; // 0x4C
|
||||
uint8_t RegPaDac; // 0x4D
|
||||
// Test
|
||||
uint8_t RegTestReserved4E[0x58-0x4E]; // 0x4E-0x57
|
||||
// Additional settings
|
||||
uint8_t RegTcxo; // 0x58
|
||||
// Test
|
||||
uint8_t RegTestReserved59; // 0x59
|
||||
// Test
|
||||
uint8_t RegTestReserved5B; // 0x5B
|
||||
// Additional settings
|
||||
uint8_t RegPll; // 0x5C
|
||||
// Test
|
||||
uint8_t RegTestReserved5D; // 0x5D
|
||||
// Additional settings
|
||||
uint8_t RegPllLowPn; // 0x5E
|
||||
// Test
|
||||
uint8_t RegTestReserved5F[0x6C - 0x5F]; // 0x5F-0x6B
|
||||
// Additional settings
|
||||
uint8_t RegFormerTemp; // 0x6C
|
||||
// Test
|
||||
uint8_t RegTestReserved6D[0x71 - 0x6D]; // 0x6D-0x70
|
||||
}tSX1276LR;
|
||||
|
||||
extern tSX1276LR* SX1276LR;
|
||||
|
||||
//初始化SX1276LoRa模式
|
||||
void SX1276LoRaInit( void );
|
||||
|
||||
//读SX1276的版本号
|
||||
void SX1276LoRaSetDefaults( void );
|
||||
|
||||
//启用/禁用LoRa模式
|
||||
void SX1276LoRaSetLoRaOn( bool enable );
|
||||
|
||||
//设置SX1276操作模式
|
||||
void SX1276LoRaSetOpMode( uint8_t opMode );
|
||||
|
||||
//获取SX1276操作模式
|
||||
uint8_t SX1276LoRaGetOpMode( void );
|
||||
|
||||
//读取SX1276低噪声放大器(信号放大)的增益,
|
||||
uint8_t SX1276LoRaReadRxGain( void );
|
||||
|
||||
//读取lora模式下无线信号强度
|
||||
double SX1276LoRaReadRssi( void );
|
||||
|
||||
//获取数据时的增益值
|
||||
uint8_t SX1276LoRaGetPacketRxGain( void );
|
||||
|
||||
//获取数据时的信噪比值,信号和噪声的比值,信噪比越高,说明信号干扰越小。
|
||||
int8_t SX1276LoRaGetPacketSnr( void );
|
||||
|
||||
//获取数据时的无线信号强度
|
||||
double SX1276LoRaGetPacketRssi( void );
|
||||
|
||||
//开始接收
|
||||
void SX1276LoRaStartRx( void );
|
||||
|
||||
//接收数据
|
||||
void SX1276LoRaGetRxPacket( void *buffer, uint16_t *size );
|
||||
|
||||
//发送数据
|
||||
void SX1276LoRaSetTxPacket( const void *buffer, uint16_t size );
|
||||
|
||||
//得到RFLRState状态
|
||||
uint8_t SX1276LoRaGetRFState( void );
|
||||
|
||||
//设置RFLRState状态,RFLRState的值决定了下面的函数处理哪一步的代码
|
||||
void SX1276LoRaSetRFState( uint8_t state );
|
||||
|
||||
//SX1276模块接发收数据的处理函数
|
||||
uint32_t SX1276LoRaProcess( void );
|
||||
|
||||
uint32_t SX1276LoraChannelEmpty( void );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-LoRaMisc.c
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-LoRaMisc.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
#include "platform.h"
|
||||
|
||||
#if defined( USE_SX1276_RADIO )
|
||||
|
||||
#include "sx1276-Hal.h"
|
||||
#include "sx1276.h"
|
||||
|
||||
#include "sx1276-LoRa.h"
|
||||
#include "sx1276-LoRaMisc.h"
|
||||
|
||||
/*!
|
||||
* SX1276 definitions
|
||||
*/
|
||||
#define XTAL_FREQ 32000000
|
||||
#define FREQ_STEP 61.03515625
|
||||
|
||||
extern tLoRaSettings LoRaSettings;
|
||||
|
||||
void SX1276LoRaSetRFFrequency( uint32_t freq )
|
||||
{
|
||||
LoRaSettings.RFFrequency = freq;
|
||||
|
||||
freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP );
|
||||
SX1276LR->RegFrfMsb = ( uint8_t )( ( freq >> 16 ) & 0xFF );
|
||||
SX1276LR->RegFrfMid = ( uint8_t )( ( freq >> 8 ) & 0xFF );
|
||||
SX1276LR->RegFrfLsb = ( uint8_t )( freq & 0xFF );
|
||||
SX1276WriteBuffer( REG_LR_FRFMSB, &SX1276LR->RegFrfMsb, 3 );
|
||||
}
|
||||
|
||||
uint32_t SX1276LoRaGetRFFrequency( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_LR_FRFMSB, &SX1276LR->RegFrfMsb, 3 );
|
||||
LoRaSettings.RFFrequency = ( ( uint32_t )SX1276LR->RegFrfMsb << 16 ) | ( ( uint32_t )SX1276LR->RegFrfMid << 8 ) | ( ( uint32_t )SX1276LR->RegFrfLsb );
|
||||
LoRaSettings.RFFrequency = ( uint32_t )( ( double )LoRaSettings.RFFrequency * ( double )FREQ_STEP );
|
||||
|
||||
return LoRaSettings.RFFrequency;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetRFPower( int8_t power )
|
||||
{
|
||||
SX1276Read( REG_LR_PACONFIG, &SX1276LR->RegPaConfig );
|
||||
SX1276Read( REG_LR_PADAC, &SX1276LR->RegPaDac );
|
||||
|
||||
if( ( SX1276LR->RegPaConfig & RFLR_PACONFIG_PASELECT_PABOOST ) == RFLR_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( ( SX1276LR->RegPaDac & 0x87 ) == 0x87 )
|
||||
{
|
||||
if( power < 5 )
|
||||
{
|
||||
power = 5;
|
||||
}
|
||||
if( power > 20 )
|
||||
{
|
||||
power = 20;
|
||||
}
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( power < 2 )
|
||||
{
|
||||
power = 2;
|
||||
}
|
||||
if( power > 17 )
|
||||
{
|
||||
power = 17;
|
||||
}
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( power < -1 )
|
||||
{
|
||||
power = -1;
|
||||
}
|
||||
if( power > 14 )
|
||||
{
|
||||
power = 14;
|
||||
}
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_MAX_POWER_MASK ) | 0x70;
|
||||
SX1276LR->RegPaConfig = ( SX1276LR->RegPaConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
|
||||
}
|
||||
SX1276Write( REG_LR_PACONFIG, SX1276LR->RegPaConfig );
|
||||
LoRaSettings.Power = power;
|
||||
}
|
||||
|
||||
int8_t SX1276LoRaGetRFPower( void )
|
||||
{
|
||||
SX1276Read( REG_LR_PACONFIG, &SX1276LR->RegPaConfig );
|
||||
SX1276Read( REG_LR_PADAC, &SX1276LR->RegPaDac );
|
||||
|
||||
if( ( SX1276LR->RegPaConfig & RFLR_PACONFIG_PASELECT_PABOOST ) == RFLR_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( ( SX1276LR->RegPaDac & 0x07 ) == 0x07 )
|
||||
{
|
||||
LoRaSettings.Power = 5 + ( SX1276LR->RegPaConfig & ~RFLR_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
else
|
||||
{
|
||||
LoRaSettings.Power = 2 + ( SX1276LR->RegPaConfig & ~RFLR_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoRaSettings.Power = -1 + ( SX1276LR->RegPaConfig & ~RFLR_PACONFIG_OUTPUTPOWER_MASK );
|
||||
}
|
||||
return LoRaSettings.Power;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetSignalBandwidth( uint8_t bw )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
SX1276LR->RegModemConfig1 = ( SX1276LR->RegModemConfig1 & RFLR_MODEMCONFIG1_BW_MASK ) | ( bw << 4 );
|
||||
SX1276Write( REG_LR_MODEMCONFIG1, SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.SignalBw = bw;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetSignalBandwidth( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.SignalBw = ( SX1276LR->RegModemConfig1 & ~RFLR_MODEMCONFIG1_BW_MASK ) >> 4;
|
||||
return LoRaSettings.SignalBw;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetSpreadingFactor( uint8_t factor )
|
||||
{
|
||||
|
||||
if( factor > 12 )
|
||||
{
|
||||
factor = 12;
|
||||
}
|
||||
else if( factor < 6 )
|
||||
{
|
||||
factor = 6;
|
||||
}
|
||||
|
||||
if( factor == 6 )
|
||||
{
|
||||
SX1276LoRaSetNbTrigPeaks( 5 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276LoRaSetNbTrigPeaks( 3 );
|
||||
}
|
||||
|
||||
SX1276Read( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2 );
|
||||
SX1276LR->RegModemConfig2 = ( SX1276LR->RegModemConfig2 & RFLR_MODEMCONFIG2_SF_MASK ) | ( factor << 4 );
|
||||
SX1276Write( REG_LR_MODEMCONFIG2, SX1276LR->RegModemConfig2 );
|
||||
LoRaSettings.SpreadingFactor = factor;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetSpreadingFactor( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2 );
|
||||
LoRaSettings.SpreadingFactor = ( SX1276LR->RegModemConfig2 & ~RFLR_MODEMCONFIG2_SF_MASK ) >> 4;
|
||||
return LoRaSettings.SpreadingFactor;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetErrorCoding( uint8_t value )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
SX1276LR->RegModemConfig1 = ( SX1276LR->RegModemConfig1 & RFLR_MODEMCONFIG1_CODINGRATE_MASK ) | ( value << 1 );
|
||||
SX1276Write( REG_LR_MODEMCONFIG1, SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.ErrorCoding = value;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetErrorCoding( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.ErrorCoding = ( SX1276LR->RegModemConfig1 & ~RFLR_MODEMCONFIG1_CODINGRATE_MASK ) >> 1;
|
||||
return LoRaSettings.ErrorCoding;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPacketCrcOn( bool enable )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2 );
|
||||
SX1276LR->RegModemConfig2 = ( SX1276LR->RegModemConfig2 & RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK ) | ( enable << 2 );
|
||||
SX1276Write( REG_LR_MODEMCONFIG2, SX1276LR->RegModemConfig2 );
|
||||
LoRaSettings.CrcOn = enable;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPreambleLength( uint16_t value )
|
||||
{
|
||||
SX1276ReadBuffer( REG_LR_PREAMBLEMSB, &SX1276LR->RegPreambleMsb, 2 );
|
||||
|
||||
SX1276LR->RegPreambleMsb = ( value >> 8 ) & 0x00FF;
|
||||
SX1276LR->RegPreambleLsb = value & 0xFF;
|
||||
SX1276WriteBuffer( REG_LR_PREAMBLEMSB, &SX1276LR->RegPreambleMsb, 2 );
|
||||
}
|
||||
|
||||
uint16_t SX1276LoRaGetPreambleLength( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_LR_PREAMBLEMSB, &SX1276LR->RegPreambleMsb, 2 );
|
||||
return ( ( SX1276LR->RegPreambleMsb & 0x00FF ) << 8 ) | SX1276LR->RegPreambleLsb;
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetPacketCrcOn( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2 );
|
||||
LoRaSettings.CrcOn = ( SX1276LR->RegModemConfig2 & RFLR_MODEMCONFIG2_RXPAYLOADCRC_ON ) >> 1;
|
||||
return LoRaSettings.CrcOn;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetImplicitHeaderOn( bool enable )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
SX1276LR->RegModemConfig1 = ( SX1276LR->RegModemConfig1 & RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK ) | ( enable );
|
||||
SX1276Write( REG_LR_MODEMCONFIG1, SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.ImplicitHeaderOn = enable;
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetImplicitHeaderOn( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG1, &SX1276LR->RegModemConfig1 );
|
||||
LoRaSettings.ImplicitHeaderOn = ( SX1276LR->RegModemConfig1 & RFLR_MODEMCONFIG1_IMPLICITHEADER_ON );
|
||||
return LoRaSettings.ImplicitHeaderOn;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetRxSingleOn( bool enable )
|
||||
{
|
||||
LoRaSettings.RxSingleOn = enable;
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetRxSingleOn( void )
|
||||
{
|
||||
return LoRaSettings.RxSingleOn;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetFreqHopOn( bool enable )
|
||||
{
|
||||
LoRaSettings.FreqHopOn = enable;
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetFreqHopOn( void )
|
||||
{
|
||||
return LoRaSettings.FreqHopOn;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetHopPeriod( uint8_t value )
|
||||
{
|
||||
SX1276LR->RegHopPeriod = value;
|
||||
SX1276Write( REG_LR_HOPPERIOD, SX1276LR->RegHopPeriod );
|
||||
LoRaSettings.HopPeriod = value;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetHopPeriod( void )
|
||||
{
|
||||
SX1276Read( REG_LR_HOPPERIOD, &SX1276LR->RegHopPeriod );
|
||||
LoRaSettings.HopPeriod = SX1276LR->RegHopPeriod;
|
||||
return LoRaSettings.HopPeriod;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetTxPacketTimeout( uint32_t value )
|
||||
{
|
||||
LoRaSettings.TxPacketTimeout = value;
|
||||
}
|
||||
|
||||
uint32_t SX1276LoRaGetTxPacketTimeout( void )
|
||||
{
|
||||
return LoRaSettings.TxPacketTimeout;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetRxPacketTimeout( uint32_t value )
|
||||
{
|
||||
LoRaSettings.RxPacketTimeout = value;
|
||||
}
|
||||
|
||||
uint32_t SX1276LoRaGetRxPacketTimeout( void )
|
||||
{
|
||||
return LoRaSettings.RxPacketTimeout;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPayloadLength( uint8_t value )
|
||||
{
|
||||
SX1276LR->RegPayloadLength = value;
|
||||
SX1276Write( REG_LR_PAYLOADLENGTH, SX1276LR->RegPayloadLength );
|
||||
LoRaSettings.PayloadLength = value;
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetPayloadLength( void )
|
||||
{
|
||||
SX1276Read( REG_LR_PAYLOADLENGTH, &SX1276LR->RegPayloadLength );
|
||||
LoRaSettings.PayloadLength = SX1276LR->RegPayloadLength;
|
||||
return LoRaSettings.PayloadLength;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPa20dBm( bool enale )
|
||||
{
|
||||
SX1276Read( REG_LR_PADAC, &SX1276LR->RegPaDac );
|
||||
SX1276Read( REG_LR_PACONFIG, &SX1276LR->RegPaConfig );
|
||||
|
||||
if( ( SX1276LR->RegPaConfig & RFLR_PACONFIG_PASELECT_PABOOST ) == RFLR_PACONFIG_PASELECT_PABOOST )
|
||||
{
|
||||
if( enale == true )
|
||||
{
|
||||
SX1276LR->RegPaDac = 0x87;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SX1276LR->RegPaDac = 0x84;
|
||||
}
|
||||
SX1276Write( REG_LR_PADAC, SX1276LR->RegPaDac );
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetPa20dBm( void )
|
||||
{
|
||||
SX1276Read( REG_LR_PADAC, &SX1276LR->RegPaDac );
|
||||
|
||||
return ( ( SX1276LR->RegPaDac & 0x07 ) == 0x07 ) ? true : false;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPAOutput( uint8_t outputPin )
|
||||
{
|
||||
SX1276Read( REG_LR_PACONFIG, &SX1276LR->RegPaConfig );
|
||||
SX1276LR->RegPaConfig = (SX1276LR->RegPaConfig & RFLR_PACONFIG_PASELECT_MASK ) | outputPin;
|
||||
SX1276Write( REG_LR_PACONFIG, SX1276LR->RegPaConfig );
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetPAOutput( void )
|
||||
{
|
||||
SX1276Read( REG_LR_PACONFIG, &SX1276LR->RegPaConfig );
|
||||
return SX1276LR->RegPaConfig & ~RFLR_PACONFIG_PASELECT_MASK;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetPaRamp( uint8_t value )
|
||||
{
|
||||
SX1276Read( REG_LR_PARAMP, &SX1276LR->RegPaRamp );
|
||||
SX1276LR->RegPaRamp = ( SX1276LR->RegPaRamp & RFLR_PARAMP_MASK ) | ( value & ~RFLR_PARAMP_MASK );
|
||||
SX1276Write( REG_LR_PARAMP, SX1276LR->RegPaRamp );
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetPaRamp( void )
|
||||
{
|
||||
SX1276Read( REG_LR_PARAMP, &SX1276LR->RegPaRamp );
|
||||
return SX1276LR->RegPaRamp & ~RFLR_PARAMP_MASK;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetSymbTimeout( uint16_t value )
|
||||
{
|
||||
SX1276ReadBuffer( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2, 2 );
|
||||
|
||||
SX1276LR->RegModemConfig2 = ( SX1276LR->RegModemConfig2 & RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) | ( ( value >> 8 ) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK );
|
||||
SX1276LR->RegSymbTimeoutLsb = value & 0xFF;
|
||||
SX1276WriteBuffer( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2, 2 );
|
||||
}
|
||||
|
||||
uint16_t SX1276LoRaGetSymbTimeout( void )
|
||||
{
|
||||
SX1276ReadBuffer( REG_LR_MODEMCONFIG2, &SX1276LR->RegModemConfig2, 2 );
|
||||
return ( ( SX1276LR->RegModemConfig2 & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) << 8 ) | SX1276LR->RegSymbTimeoutLsb;
|
||||
}
|
||||
|
||||
void SX1276LoRaSetLowDatarateOptimize( bool enable )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG3, &SX1276LR->RegModemConfig3 );
|
||||
SX1276LR->RegModemConfig3 = ( SX1276LR->RegModemConfig3 & RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) | ( enable << 3 );
|
||||
SX1276Write( REG_LR_MODEMCONFIG3, SX1276LR->RegModemConfig3 );
|
||||
}
|
||||
|
||||
bool SX1276LoRaGetLowDatarateOptimize( void )
|
||||
{
|
||||
SX1276Read( REG_LR_MODEMCONFIG3, &SX1276LR->RegModemConfig3 );
|
||||
return ( ( SX1276LR->RegModemConfig3 & RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON ) >> 3 );
|
||||
}
|
||||
|
||||
void SX1276LoRaSetNbTrigPeaks( uint8_t value )
|
||||
{
|
||||
SX1276Read( 0x31, &SX1276LR->RegTestReserved31 );
|
||||
SX1276LR->RegTestReserved31 = ( SX1276LR->RegTestReserved31 & 0xF8 ) | value;//数据包长度最高有效位 0x31 bit2 1 0
|
||||
SX1276Write( 0x31, SX1276LR->RegTestReserved31 );
|
||||
}
|
||||
|
||||
uint8_t SX1276LoRaGetNbTrigPeaks( void )
|
||||
{
|
||||
SX1276Read( 0x31, &SX1276LR->RegTestReserved31 );
|
||||
return ( SX1276LR->RegTestReserved31 & 0x07 );
|
||||
}
|
||||
|
||||
#endif // USE_SX1276_RADIO
|
||||
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276-LoRaMisc.h
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276-LoRaMisc.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
#ifndef __SX1276_LORA_MISC_H__
|
||||
#define __SX1276_LORA_MISC_H__
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
/*!
|
||||
* \brief Writes the new RF frequency value
|
||||
*
|
||||
* \param [IN] freq New RF frequency value in [Hz]
|
||||
*/
|
||||
void SX1276LoRaSetRFFrequency( uint32_t freq );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current RF frequency value
|
||||
*
|
||||
* \retval freq Current RF frequency value in [Hz]
|
||||
*/
|
||||
uint32_t SX1276LoRaGetRFFrequency( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new RF output power value
|
||||
*
|
||||
* \param [IN] power New output power value in [dBm]
|
||||
*/
|
||||
void SX1276LoRaSetRFPower( int8_t power );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current RF output power value
|
||||
*
|
||||
* \retval power Current output power value in [dBm]
|
||||
*/
|
||||
int8_t SX1276LoRaGetRFPower( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new Signal Bandwidth value
|
||||
*
|
||||
* \remark This function sets the IF frequency according to the datasheet
|
||||
*
|
||||
* \param [IN] factor New Signal Bandwidth value [0: 125 kHz, 1: 250 kHz, 2: 500 kHz]
|
||||
*/
|
||||
void SX1276LoRaSetSignalBandwidth( uint8_t bw );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current Signal Bandwidth value
|
||||
*
|
||||
* \retval factor Current Signal Bandwidth value [0: 125 kHz, 1: 250 kHz, 2: 500 kHz]
|
||||
*/
|
||||
uint8_t SX1276LoRaGetSignalBandwidth( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new Spreading Factor value
|
||||
*
|
||||
* \param [IN] factor New Spreading Factor value [7, 8, 9, 10, 11, 12]
|
||||
*/
|
||||
void SX1276LoRaSetSpreadingFactor( uint8_t factor );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current Spreading Factor value
|
||||
*
|
||||
* \retval factor Current Spreading Factor value [7, 8, 9, 10, 11, 12]
|
||||
*/
|
||||
uint8_t SX1276LoRaGetSpreadingFactor( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new Error Coding value
|
||||
*
|
||||
* \param [IN] value New Error Coding value [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
|
||||
*/
|
||||
void SX1276LoRaSetErrorCoding( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current Error Coding value
|
||||
*
|
||||
* \retval value Current Error Coding value [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
|
||||
*/
|
||||
uint8_t SX1276LoRaGetErrorCoding( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables the packet CRC generation
|
||||
*
|
||||
* \param [IN] enaable [true, false]
|
||||
*/
|
||||
void SX1276LoRaSetPacketCrcOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current packet CRC generation status
|
||||
*
|
||||
* \retval enable [true, false]
|
||||
*/
|
||||
bool SX1276LoRaGetPacketCrcOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables the Implicit Header mode in LoRa
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
void SX1276LoRaSetImplicitHeaderOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Check if implicit header mode in LoRa in enabled or disabled
|
||||
*
|
||||
* \retval enable [true, false]
|
||||
*/
|
||||
bool SX1276LoRaGetImplicitHeaderOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables Rx single instead of Rx continuous
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
void SX1276LoRaSetRxSingleOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Check if LoRa is in Rx Single mode
|
||||
*
|
||||
* \retval enable [true, false]
|
||||
*/
|
||||
bool SX1276LoRaGetRxSingleOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables the frequency hopping
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
|
||||
void SX1276LoRaSetFreqHopOn( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Get the frequency hopping status
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
bool SX1276LoRaGetFreqHopOn( void );
|
||||
|
||||
/*!
|
||||
* \brief Set symbol period between frequency hops
|
||||
*
|
||||
* \param [IN] value
|
||||
*/
|
||||
void SX1276LoRaSetHopPeriod( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get symbol period between frequency hops
|
||||
*
|
||||
* \retval value symbol period between frequency hops
|
||||
*/
|
||||
uint8_t SX1276LoRaGetHopPeriod( void );
|
||||
|
||||
/*!
|
||||
* \brief Set timeout Tx packet (based on MCU timer, timeout between Tx Mode entry Tx Done IRQ)
|
||||
*
|
||||
* \param [IN] value timeout (ms)
|
||||
*/
|
||||
void SX1276LoRaSetTxPacketTimeout( uint32_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get timeout between Tx packet (based on MCU timer, timeout between Tx Mode entry Tx Done IRQ)
|
||||
*
|
||||
* \retval value timeout (ms)
|
||||
*/
|
||||
uint32_t SX1276LoRaGetTxPacketTimeout( void );
|
||||
|
||||
/*!
|
||||
* \brief Set timeout Rx packet (based on MCU timer, timeout between Rx Mode entry and Rx Done IRQ)
|
||||
*
|
||||
* \param [IN] value timeout (ms)
|
||||
*/
|
||||
void SX1276LoRaSetRxPacketTimeout( uint32_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get timeout Rx packet (based on MCU timer, timeout between Rx Mode entry and Rx Done IRQ)
|
||||
*
|
||||
* \retval value timeout (ms)
|
||||
*/
|
||||
uint32_t SX1276LoRaGetRxPacketTimeout( void );
|
||||
|
||||
/*!
|
||||
* \brief Set payload length
|
||||
*
|
||||
* \param [IN] value payload length
|
||||
*/
|
||||
void SX1276LoRaSetPayloadLength( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get payload length
|
||||
*
|
||||
* \retval value payload length
|
||||
*/
|
||||
uint8_t SX1276LoRaGetPayloadLength( void );
|
||||
|
||||
/*!
|
||||
* \brief Enables/Disables the 20 dBm PA
|
||||
*
|
||||
* \param [IN] enable [true, false]
|
||||
*/
|
||||
void SX1276LoRaSetPa20dBm( bool enale );
|
||||
|
||||
/*!
|
||||
* \brief Gets the current 20 dBm PA status
|
||||
*
|
||||
* \retval enable [true, false]
|
||||
*/
|
||||
bool SX1276LoRaGetPa20dBm( void );
|
||||
|
||||
/*!
|
||||
* \brief Set the RF Output pin
|
||||
*
|
||||
* \param [IN] RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
|
||||
*/
|
||||
void SX1276LoRaSetPAOutput( uint8_t outputPin );
|
||||
|
||||
/*!
|
||||
* \brief Gets the used RF Ouptut pin
|
||||
*
|
||||
* \retval RF_PACONFIG_PASELECT_PABOOST or RF_PACONFIG_PASELECT_RFO
|
||||
*/
|
||||
uint8_t SX1276LoRaGetPAOutput( void );
|
||||
|
||||
/*!
|
||||
* \brief Writes the new PA rise/fall time of ramp up/down value
|
||||
*
|
||||
* \param [IN] value New PaRamp value
|
||||
*/
|
||||
void SX1276LoRaSetPaRamp( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Reads the current PA rise/fall time of ramp up/down value
|
||||
*
|
||||
* \retval freq Current PaRamp value
|
||||
*/
|
||||
uint8_t SX1276LoRaGetPaRamp( void );
|
||||
|
||||
/*!
|
||||
* \brief Set Symbol Timeout based on symbol length
|
||||
*
|
||||
* \param [IN] value number of symbol
|
||||
*/
|
||||
void SX1276LoRaSetSymbTimeout( uint16_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get Symbol Timeout based on symbol length
|
||||
*
|
||||
* \retval value number of symbol
|
||||
*/
|
||||
uint16_t SX1276LoRaGetSymbTimeout( void );
|
||||
|
||||
/*!
|
||||
* \brief Configure the device to optimize low datarate transfers
|
||||
*
|
||||
* \param [IN] enable Enables/Disables the low datarate optimization
|
||||
*/
|
||||
void SX1276LoRaSetLowDatarateOptimize( bool enable );
|
||||
|
||||
/*!
|
||||
* \brief Get the status of optimize low datarate transfers
|
||||
*
|
||||
* \retval LowDatarateOptimize enable or disable
|
||||
*/
|
||||
bool SX1276LoRaGetLowDatarateOptimize( void );
|
||||
|
||||
/*!
|
||||
* \brief Get the preamble length
|
||||
*
|
||||
* \retval value preamble length
|
||||
*/
|
||||
uint16_t SX1276LoRaGetPreambleLength( void );
|
||||
|
||||
/*!
|
||||
* \brief Set the preamble length
|
||||
*
|
||||
* \param [IN] value preamble length
|
||||
*/
|
||||
void SX1276LoRaSetPreambleLength( uint16_t value );
|
||||
|
||||
/*!
|
||||
* \brief Set the number or rolling preamble symbol needed for detection
|
||||
*
|
||||
* \param [IN] value number of preamble symbol
|
||||
*/
|
||||
void SX1276LoRaSetNbTrigPeaks( uint8_t value );
|
||||
|
||||
/*!
|
||||
* \brief Get the number or rolling preamble symbol needed for detection
|
||||
*
|
||||
* \retval value number of preamble symbol
|
||||
*/
|
||||
uint8_t SX1276LoRaGetNbTrigPeaks( void );
|
||||
#endif
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276.c
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276.c
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
#include "platform.h"
|
||||
#include "radio.h"
|
||||
|
||||
#if defined(USE_SX1276_RADIO)
|
||||
#include "sx1276.h"
|
||||
#include "sx1276-Hal.h"
|
||||
#include "sx1276-Fsk.h"
|
||||
#include "sx1276-LoRa.h"
|
||||
|
||||
uint8_t SX1276Regs[0x70];
|
||||
|
||||
static bool LoRaOn = true;
|
||||
static bool LoRaOnState = false;
|
||||
|
||||
void SX1276Reset(void)
|
||||
{
|
||||
uint32_t startTick;
|
||||
|
||||
SX1276SetReset(RADIO_RESET_ON);
|
||||
|
||||
DDL_DelayMS(1);
|
||||
|
||||
SX1276SetReset(RADIO_RESET_OFF);
|
||||
|
||||
DDL_DelayMS(6);
|
||||
}
|
||||
|
||||
void SX1276_SetLoRaOn(bool enable)
|
||||
{
|
||||
if(LoRaOnState == enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoRaOnState = enable;
|
||||
LoRaOn = enable;
|
||||
|
||||
if(LoRaOn == true) {
|
||||
SX1276LoRaSetOpMode(RFLR_OPMODE_SLEEP);
|
||||
|
||||
SX1276LR->RegOpMode = (SX1276LR->RegOpMode & RFLR_OPMODE_LONGRANGEMODE_MASK) | RFLR_OPMODE_LONGRANGEMODE_ON;
|
||||
SX1276Write(REG_LR_OPMODE, SX1276LR->RegOpMode);
|
||||
|
||||
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
|
||||
|
||||
// RxDone RxTimeout FhssChangeChannel CadDone
|
||||
SX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
|
||||
// CadDetected ModeReady
|
||||
SX1276LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
|
||||
SX1276WriteBuffer(REG_LR_DIOMAPPING1, &SX1276LR->RegDioMapping1, 2);
|
||||
|
||||
SX1276ReadBuffer(REG_LR_OPMODE, SX1276Regs + 1, 0x70 - 1);
|
||||
} else {
|
||||
SX1276LoRaSetOpMode(RFLR_OPMODE_SLEEP);
|
||||
|
||||
SX1276LR->RegOpMode = (SX1276LR->RegOpMode & RFLR_OPMODE_LONGRANGEMODE_MASK) | RFLR_OPMODE_LONGRANGEMODE_OFF;
|
||||
SX1276Write(REG_LR_OPMODE, SX1276LR->RegOpMode);
|
||||
|
||||
SX1276LoRaSetOpMode(RFLR_OPMODE_STANDBY);
|
||||
|
||||
SX1276ReadBuffer(REG_OPMODE, SX1276Regs + 1, 0x70 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SX1276_GetLoRaOn(void)
|
||||
{
|
||||
return LoRaOn;
|
||||
}
|
||||
|
||||
void SX1276SetOpMode(uint8_t opMode)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
SX1276FskSetOpMode(opMode);
|
||||
} else {
|
||||
SX1276LoRaSetOpMode(opMode);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276_GetOpMode(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskGetOpMode();
|
||||
} else {
|
||||
return SX1276LoRaGetOpMode();
|
||||
}
|
||||
}
|
||||
|
||||
double SX1276ReadRssi(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskReadRssi();
|
||||
} else {
|
||||
return SX1276LoRaReadRssi();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276_ReadRxGain(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskReadRxGain();
|
||||
} else {
|
||||
return SX1276LoRaReadRxGain();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276_GetPacketRxGain(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskGetPacketRxGain();
|
||||
} else {
|
||||
return SX1276LoRaGetPacketRxGain();
|
||||
}
|
||||
}
|
||||
|
||||
int8_t SX1276_GetPacketSnr(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
while(1) {
|
||||
// Useless in FSK mode
|
||||
// Block program here
|
||||
}
|
||||
} else {
|
||||
return SX1276LoRaGetPacketSnr();
|
||||
}
|
||||
}
|
||||
|
||||
double SX1276_GetPacketRssi(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskGetPacketRssi();
|
||||
} else {
|
||||
return SX1276LoRaGetPacketRssi();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SX1276GetPacketAfc(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskGetPacketAfc();
|
||||
} else {
|
||||
while(1) {
|
||||
// Useless in LoRa mode
|
||||
// Block program here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276StartRx(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
SX1276FskSetRFState(RF_STATE_RX_INIT);
|
||||
} else {
|
||||
SX1276LoRaSetRFState(RFLR_STATE_RX_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276GetRxPacket(void *buffer, uint16_t *size)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
SX1276FskGetRxPacket(buffer, size);
|
||||
} else {
|
||||
SX1276LoRaGetRxPacket(buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276SetTxPacket(const void *buffer, uint16_t size)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
SX1276FskSetTxPacket(buffer, size);
|
||||
} else {
|
||||
SX1276LoRaSetTxPacket(buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SX1276GetRFState(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskGetRFState();
|
||||
} else {
|
||||
return SX1276LoRaGetRFState();
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276SetRFState(uint8_t state)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
SX1276FskSetRFState(state);
|
||||
} else {
|
||||
SX1276LoRaSetRFState(state);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SX1276Process(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return SX1276FskProcess();
|
||||
} else {
|
||||
return SX1276LoRaProcess();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SX1276ChannelEmpty(void)
|
||||
{
|
||||
if(LoRaOn == false) {
|
||||
return true;
|
||||
} else {
|
||||
SX1276LoraChannelEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276Init(void)
|
||||
{
|
||||
uint8_t TempReg;
|
||||
|
||||
SX1276 = (tSX1276 *)SX1276Regs;
|
||||
SX1276LR = (tSX1276LR *)SX1276Regs;
|
||||
|
||||
SX1276InitIo();
|
||||
|
||||
SX1276Reset();
|
||||
|
||||
SX1276Read(0x06, &TempReg);
|
||||
|
||||
if(TempReg != 0x6C) {
|
||||
KPrintf("Hard SPI Err!\r\n");
|
||||
}
|
||||
|
||||
SX1276Read(0x42, &TempReg);
|
||||
|
||||
if(TempReg != 0x12) {
|
||||
KPrintf("Hard SPI Err! version 0x%x\r\n", TempReg);
|
||||
}
|
||||
|
||||
#if (LORA == 0)
|
||||
LoRaOn = false;
|
||||
SX1276_SetLoRaOn(LoRaOn);
|
||||
SX1276FskInit();
|
||||
#else
|
||||
LoRaOn = true;
|
||||
SX1276_SetLoRaOn(LoRaOn);
|
||||
SX1276LoRaInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
|
||||
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
|
||||
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
|
||||
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
|
||||
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* Copyright (C) SEMTECH S.A.
|
||||
*/
|
||||
/*!
|
||||
* \file sx1276.h
|
||||
* \brief SX1276 RF chip high level functions driver
|
||||
*
|
||||
* \remark Optional support functions.
|
||||
* These functions are defined only to easy the change of the
|
||||
* parameters.
|
||||
* For a final firmware the radio parameters will be known so
|
||||
* there is no need to support all possible parameters.
|
||||
* Removing these functions will greatly reduce the final firmware
|
||||
* size.
|
||||
*
|
||||
* \version 2.0.0
|
||||
* \date May 6 2013
|
||||
* \author Gregory Cristian
|
||||
*
|
||||
* Last modified by Miguel Luis on Jun 19 2013
|
||||
*/
|
||||
/*************************************************
|
||||
File name: sx1276.h
|
||||
Description: support aiit board configure and register function
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. replace original macro and basic date type with AIIT XUOS Lab's own defination
|
||||
*************************************************/
|
||||
|
||||
|
||||
#ifndef __SX1276_H__
|
||||
#define __SX1276_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern uint8_t SX1276Regs[0x70]; //SX1276寄存器数组
|
||||
|
||||
void SX1276Init( void ); //初始化SX1276
|
||||
|
||||
void SX1276Reset( void ); //重置SX1276
|
||||
|
||||
/*以下函数都没有被使用到,因为在sx1276-LoRa.h里面又定义了一系列与下面作用相同的函数*/
|
||||
void SX1276_SetLoRaOn( bool enable ); //启用LoRa调制解调器或FSK调制解调器
|
||||
|
||||
bool SX1276_GetLoRaOn( void ); //获取LoRa调制解调器状态
|
||||
|
||||
void SX1276SetOpMode( uint8_t opMode ); //设置SX1276操作模式
|
||||
|
||||
uint8_t SX1276_GetOpMode( void ); //获取SX1276操作模式
|
||||
|
||||
uint8_t SX1276_ReadRxGain( void ); //读取当前Rx增益设置
|
||||
|
||||
double SX1276ReadRssi( void ); //读取无线信号强度
|
||||
|
||||
uint8_t SX1276_GetPacketRxGain( void ); //获取数据时的增益值
|
||||
|
||||
int8_t SX1276_GetPacketSnr( void ); //获取数据时的信噪比值,信号和噪声的比值,信噪比越高,说明信号干扰越小。
|
||||
|
||||
double SX1276_GetPacketRssi( void ); //获取数据是的无线信号强度
|
||||
|
||||
/*!
|
||||
* \brief Gets the AFC value measured while receiving the packet
|
||||
*
|
||||
* \retval afcValue Current AFC value in [Hz]
|
||||
*/
|
||||
uint32_t SX1276GetPacketAfc( void ); //此函数不知道作用
|
||||
|
||||
|
||||
void SX1276StartRx( void ); //开始接收
|
||||
|
||||
void SX1276GetRxPacket( void *buffer, uint16_t *size ); //得到接收的数据
|
||||
|
||||
void SX1276SetTxPacket( const void *buffer, uint16_t size ); //发送数据
|
||||
|
||||
uint8_t SX1276GetRFState( void ); //得到RFLRState状态
|
||||
|
||||
void SX1276SetRFState( uint8_t state ); //设置RFLRState状态,RFLRState的值决定了下面的函数处理哪一步的代码
|
||||
|
||||
uint32_t SX1276Process( void ); //SX1276模块接发收数据的处理函数
|
||||
|
||||
uint32_t SX1276ChannelEmpty( void );
|
||||
|
||||
#endif
|
||||
@@ -104,12 +104,22 @@ struct SerialHardwareDevice serial_device_3;
|
||||
|
||||
void Uart3RxIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
SerialSetIsr(&serial_device_3, SERIAL_EVENT_RX_IND);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
|
||||
void Uart3RxErrIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
UartRxErrIsr(&serial_bus_3, &serial_driver_3, &serial_device_3);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -120,12 +130,22 @@ struct SerialHardwareDevice serial_device_6;
|
||||
|
||||
void Uart6RxIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
SerialSetIsr(&serial_device_6, SERIAL_EVENT_RX_IND);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
|
||||
void Uart6RxErrIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
UartRxErrIsr(&serial_bus_6, &serial_driver_6, &serial_device_6);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
config BSP_USING_HC32_USBH
|
||||
bool "Using usb host by HC32 library"
|
||||
default y
|
||||
if BSP_USING_HC32_USBH
|
||||
config USB_BUS_NAME
|
||||
string "usb bus name"
|
||||
default "usb"
|
||||
config USB_DRIVER_NAME
|
||||
string "usb bus driver name"
|
||||
default "usb_drv"
|
||||
config USB_DEVICE_NAME
|
||||
string "usb bus device name"
|
||||
default "usb_dev"
|
||||
config MOUNT_USB_FS
|
||||
bool "mount usb file system : if y then not support sdcard-mount-fs"
|
||||
default y
|
||||
select MOUNT_USB
|
||||
|
||||
if MOUNT_USB_FS
|
||||
config MOUNT_USB_FS_TYPE
|
||||
int "choose file system type : FATFS(0)"
|
||||
default 0
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
SRC_DIR := hc32_usb_driver
|
||||
|
||||
SRC_FILES := connect_usb.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_usb.c
|
||||
* @brief support hc32f4a0-board usb function and register to bus framework
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-07
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: connect_usb.c
|
||||
Description: support hc32f4a0-board usb function and register to bus framework
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-11-07
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support hc32f4a0-board usb configure, write and read
|
||||
2. support hc32f4a0-board usb bus device and driver register
|
||||
*************************************************/
|
||||
|
||||
#include <connect_usb.h>
|
||||
|
||||
usb_core_instance usb_app_instance;
|
||||
USBH_HOST usb_app_host;
|
||||
|
||||
static void UsbHostTask(void *parameter);
|
||||
|
||||
#if defined(FS_VFS)
|
||||
void UsbMountFileSystem()
|
||||
{
|
||||
if (MountFilesystem(USB_BUS_NAME, USB_DEVICE_NAME, USB_DRIVER_NAME, FSTYPE_FATFS, UDISK_MOUNTPOINT) == 0)
|
||||
KPrintf("Mount FAT on Udisk successful.\n");
|
||||
else
|
||||
KPrintf("Mount FAT on Udisk failed.\n");
|
||||
}
|
||||
|
||||
void UsbUnmountFileSystem()
|
||||
{
|
||||
UnmountFileSystem(UDISK_MOUNTPOINT);
|
||||
}
|
||||
|
||||
#ifdef MOUNT_USB
|
||||
int MountUsb(void)
|
||||
{
|
||||
int32 usb_host_task = 0;
|
||||
usb_host_task = KTaskCreate("usbh", UsbHostTask, NONE,
|
||||
USB_HOST_STACK_SIZE, 8);
|
||||
if(usb_host_task < 0) {
|
||||
KPrintf("usb_host_task create failed ...%s %d.\n", __FUNCTION__, __LINE__);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
StartupKTask(usb_host_task);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint32 UsbHostOpen(void *dev)
|
||||
{
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 UsbHostClose(void *dev)
|
||||
{
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 UsbHostRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
|
||||
|
||||
do {
|
||||
status = usb_host_msc_Read10(&usb_app_instance, (uint8 *)read_param->buffer, read_param->pos, USB_SINGLE_BLOCK_SIZE * (uint32_t)read_param->size);
|
||||
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
|
||||
return 0;
|
||||
}
|
||||
} while (USB_HOST_MSC_BUSY == status);
|
||||
}
|
||||
|
||||
if (USB_HOST_MSC_OK == status) {
|
||||
return read_param->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32 UsbHostWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
|
||||
do {
|
||||
status = usb_host_msc_Write10(&usb_app_instance, (uint8 *)write_param->buffer, write_param->pos, USB_SINGLE_BLOCK_SIZE * (uint32_t)write_param->size);
|
||||
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
|
||||
return 0;
|
||||
}
|
||||
} while (USB_HOST_MSC_BUSY == status);
|
||||
}
|
||||
|
||||
if (USB_HOST_MSC_OK == status) {
|
||||
return write_param->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int UsbControl(struct HardwareDev *dev, struct HalDevBlockParam *block_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
|
||||
if (OPER_BLK_GETGEOME == block_param->cmd) {
|
||||
block_param->dev_block.size_perbank = USB_SINGLE_BLOCK_SIZE;
|
||||
block_param->dev_block.block_size = USB_SINGLE_BLOCK_SIZE;
|
||||
block_param->dev_block.bank_num = USB_HOST_MSC_Param.MSC_Capacity;
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
/*manage the usb device operations*/
|
||||
static const struct UsbDevDone dev_done =
|
||||
{
|
||||
.open = UsbHostOpen,
|
||||
.close = UsbHostClose,
|
||||
.write = UsbHostWrite,
|
||||
.read = UsbHostRead,
|
||||
};
|
||||
|
||||
static void UsbHostTask(void *parameter)
|
||||
{
|
||||
usb_host_init(&usb_app_instance, &usb_app_host, &USBH_MSC_cb, &USR_cb);
|
||||
while (1) {
|
||||
usb_host_mainprocess(&usb_app_instance, &usb_app_host);
|
||||
}
|
||||
}
|
||||
|
||||
/*Init usb host bus、driver*/
|
||||
static int BoardUsbBusInit(struct UsbBus *usb_bus, struct UsbDriver *usb_driver)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
/*Init the usb bus */
|
||||
ret = UsbBusInit(usb_bus, USB_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_usb_init UsbBusInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Init the usb driver*/
|
||||
ret = UsbDriverInit(usb_driver, USB_DRIVER_NAME);
|
||||
if (EOK != ret){
|
||||
KPrintf("board_usb_init UsbDriverInit error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*Attach the usb driver to the usb bus*/
|
||||
ret = UsbDriverAttachToBus(USB_DRIVER_NAME, USB_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("board_usb_init USEDriverAttachToBus error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Attach the usb device to the usb bus*/
|
||||
static int BoardUsbDevBend(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
static struct UsbHardwareDevice usb_device;
|
||||
memset(&usb_device, 0, sizeof(struct UsbHardwareDevice));
|
||||
|
||||
usb_device.dev_done = &dev_done;
|
||||
usb_device.haldev.dev_block_control = UsbControl;
|
||||
|
||||
ret = USBDeviceRegister(&usb_device, NONE, USB_DEVICE_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("USBDeviceRegister device %s error %d\n", USB_DEVICE_NAME, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = USBDeviceAttachToBus(USB_DEVICE_NAME, USB_BUS_NAME);
|
||||
if (EOK != ret) {
|
||||
KPrintf("USBDeviceAttachToBus device %s error %d\n", USB_DEVICE_NAME, ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int HwUsbHostInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
static struct UsbBus usb_bus;
|
||||
memset(&usb_bus, 0, sizeof(struct UsbBus));
|
||||
|
||||
static struct UsbDriver usb_driver;
|
||||
memset(&usb_driver, 0, sizeof(struct UsbDriver));
|
||||
|
||||
ret = BoardUsbBusInit(&usb_bus, &usb_driver);
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardUsbBusInit error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardUsbDevBend();
|
||||
if (EOK != ret) {
|
||||
KPrintf("BoardUsbDevBend error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
SRC_FILES := usb_host_user.c usb_bsp.c
|
||||
|
||||
SRC_DIR := usb_host_lib
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb/usb_host_msc/source/usb_app_conf.h
|
||||
* @brief low level driver configuration
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_APP_CONF_H__
|
||||
#define __USB_APP_CONF_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
|
||||
/* USB MODE CONFIGURATION */
|
||||
/*
|
||||
USB_FS_MODE, USB_HS_MODE, USB_HS_EXTERNAL_PHY defined comment
|
||||
(1) If only defined USB_FS_MODE:
|
||||
MCU USBFS core work in full speed using internal PHY.
|
||||
(2) If only defined USB_HS_MODE:
|
||||
MCU USBHS core work in full speed using internal PHY.
|
||||
(3) If both defined USB_HS_MODE && USB_HS_EXTERNAL_PHY
|
||||
MCU USBHS core work in high speed using external PHY.
|
||||
(4) Other combination:
|
||||
Not support, forbid!!
|
||||
*/
|
||||
|
||||
//#define USB_HS_MODE
|
||||
#define USB_FS_MODE
|
||||
|
||||
#define USE_HOST_MODE
|
||||
|
||||
#ifdef USB_HS_MODE
|
||||
#define USB_HS_EXTERNAL_PHY
|
||||
#endif
|
||||
|
||||
#ifndef USB_HS_MODE
|
||||
#ifndef USB_FS_MODE
|
||||
#error "USB_HS_MODE or USB_FS_MODE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_DEVICE_MODE
|
||||
#ifndef USE_HOST_MODE
|
||||
#error "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* USB FIFO CONFIGURATION */
|
||||
#ifdef USB_FS_MODE
|
||||
#define RX_FIFO_FS_SIZE (128U)
|
||||
#define TXH_NP_FS_FIFOSIZ (32U)
|
||||
#define TXH_P_FS_FIFOSIZ (64U)
|
||||
|
||||
#if ((RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ + TXH_P_FS_FIFOSIZ) > 640U)
|
||||
#error "The USB max FIFO size is 640 x 4 Bytes!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USB_HS_MODE
|
||||
#define RX_FIFO_HS_SIZE (512U)
|
||||
#define TXH_NP_HS_FIFOSIZ (128U)
|
||||
#define TXH_P_HS_FIFOSIZ (256U)
|
||||
|
||||
#if ((RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ + TXH_P_FS_FIFOSIZ) > 2048U)
|
||||
#error "The USB max FIFO size is 2048 x 4 Bytes!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* FUNCTION CONFIGURATION */
|
||||
#define USBH_MAX_NUM_INTERFACES (3U)
|
||||
#define USBH_MAX_NUM_ENDPOINTS (2U)
|
||||
|
||||
/* CONFIGURATION FOR MSC */
|
||||
#define USBH_MSC_MPS_SIZE (0x40U)
|
||||
//#define USB_MSC_FAT_VALID
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_APP_CONF_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb/usb_host_msc/source/usb_bsp.c
|
||||
* @brief BSP function for USB example
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file usb_bsp.c
|
||||
* @brief support hc32f4a0-board usb bsp function
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-08
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_bsp.c
|
||||
Description: support hc32f4a0-board usb bsp function
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-11-08
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. support hc32f4a0-board usb IO configure
|
||||
2. support hc32f4a0-board usb irq define
|
||||
*************************************************/
|
||||
#include <device.h>
|
||||
#include "usb_bsp.h"
|
||||
#include <usb_host_int.h>
|
||||
|
||||
extern usb_core_instance usb_app_instance;
|
||||
|
||||
/* USBFS Core*/
|
||||
#define USB_DP_PORT (GPIO_PORT_A)
|
||||
#define USB_DP_PIN (GPIO_PIN_12)
|
||||
|
||||
#define USB_DM_PORT (GPIO_PORT_A)
|
||||
#define USB_DM_PIN (GPIO_PIN_11)
|
||||
|
||||
#define USB_DRVVBUS_PORT (GPIO_PORT_C)
|
||||
#define USB_DRVVBUS_PIN (GPIO_PIN_09)
|
||||
|
||||
#define USB_VBUSDET_PORT (GPIO_PORT_A)
|
||||
#define USB_VBUSDET_PIN (GPIO_PIN_09)
|
||||
|
||||
#define USB_OC_PORT (GPIO_PORT_D)
|
||||
#define USB_OC_PIN (GPIO_PIN_15)
|
||||
|
||||
//USB HOST ISR
|
||||
static void USB_IRQ_Handler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
usb_host_isr(&usb_app_instance);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
|
||||
void usb_bsp_init(usb_core_instance *pdev)
|
||||
{
|
||||
stc_gpio_init_t stcGpioCfg;
|
||||
|
||||
/* USB clock source configurate */
|
||||
CLK_SetUSBClockSrc(CLK_USBCLK_SYSCLK_DIV5);
|
||||
|
||||
(void)GPIO_StructInit(&stcGpioCfg);
|
||||
|
||||
#ifdef USB_FS_MODE
|
||||
stcGpioCfg.u16PinAttr = PIN_ATTR_ANALOG;
|
||||
(void)GPIO_Init(USB_DM_PORT, USB_DM_PIN, &stcGpioCfg);
|
||||
(void)GPIO_Init(USB_DP_PORT, USB_DP_PIN, &stcGpioCfg);
|
||||
|
||||
GPIO_SetFunc(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN, GPIO_FUNC_10); /* VBUS */
|
||||
|
||||
FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USBFS, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void usb_bsp_nvicconfig(void)
|
||||
{
|
||||
stc_irq_signin_config_t stcIrqRegiConf;
|
||||
/* Register INT_SRC_USBFS_GLB Int to Vect.No.030 */
|
||||
stcIrqRegiConf.enIRQn = INT030_IRQn;
|
||||
/* Select interrupt function */
|
||||
#ifdef USB_FS_MODE
|
||||
stcIrqRegiConf.enIntSrc = INT_SRC_USBFS_GLB;
|
||||
#else
|
||||
stcIrqRegiConf.enIntSrc = INT_SRC_USBHS_GLB;
|
||||
#endif
|
||||
/* Callback function */
|
||||
stcIrqRegiConf.pfnCallback = &USB_IRQ_Handler;
|
||||
/* Registration IRQ */
|
||||
(void)INTC_IrqSignIn(&stcIrqRegiConf);
|
||||
/* Clear Pending */
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
|
||||
/* Set priority */
|
||||
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIO_15);
|
||||
/* Enable NVIC */
|
||||
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
|
||||
}
|
||||
|
||||
void usb_udelay(const uint32_t usec)
|
||||
{
|
||||
__IO uint32_t i;
|
||||
uint32_t j;
|
||||
j = (HCLK_VALUE + 1000000UL - 1UL) / 1000000UL * usec;
|
||||
for (i = 0UL; i < j; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
void usb_mdelay(const uint32_t msec)
|
||||
{
|
||||
usb_udelay(msec * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the IO for the Vbus and OverCurrent
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_bsp_cfgvbus(LL_USB_TypeDef *USBx)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Drive vbus
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] state the vbus state it would be.
|
||||
* @retval None
|
||||
*/
|
||||
void usb_bsp_drivevbus(LL_USB_TypeDef *USBx, uint8_t state)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb/usb_host_msc/source/usb_bsp.h
|
||||
* @brief Head file for usb_bsp.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file usb_bsp.h
|
||||
* @brief support hc32f4a0-board usb bsp function
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-08
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_bsp.h
|
||||
Description: support hc32f4a0-board usb bsp function
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-11-08
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
*************************************************/
|
||||
|
||||
#ifndef USB_BSP_H
|
||||
#define USB_BSP_H
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <usb_lib.h>
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Applications
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup USB_Host_Msc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void usb_bsp_init(usb_core_instance *pdev);
|
||||
extern void usb_udelay(const uint32_t usec);
|
||||
extern void usb_mdelay(const uint32_t msec);
|
||||
extern void usb_bsp_nvicconfig(void);
|
||||
#ifdef USE_HOST_MODE
|
||||
extern void usb_bsp_cfgvbus(LL_USB_TypeDef *USBx);
|
||||
extern void usb_bsp_drivevbus(LL_USB_TypeDef *USBx, uint8_t state);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_BSP_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := host_class host_core
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := msc
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := usb_host_msc_bot.c usb_host_msc_class.c usb_host_msc_scsi.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,449 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_bot.c
|
||||
* @brief mass storage related functions
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_msc_class.h"
|
||||
#include "usb_host_msc_scsi.h"
|
||||
#include "usb_host_msc_bot.h"
|
||||
#include "usb_host_ctrltrans.h"
|
||||
#include "usb_host_def.h"
|
||||
#include "usb_host_int.h"
|
||||
#include "usb_host_driver.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC USB Host MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
#ifdef USB_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_INTERNAL_DMA_ENABLED */
|
||||
__USB_ALIGN_BEGIN HOST_CSW_PACKET_TypeDef USBH_MSC_CSWData;
|
||||
|
||||
USB_HOST_BOTXFER_TypeDef USBH_MSC_BOTXferParam;
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
#ifdef USB_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_INTERNAL_DMA_ENABLED */
|
||||
__USB_ALIGN_BEGIN HostCBWPkt_TypeDef USBH_MSC_CBWData;
|
||||
|
||||
static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief initializes original state of the mass storage parameters
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_msc_init(usb_core_instance *pdev)
|
||||
{
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
USBH_MSC_CBWData.field.CBWSignature = HOST_MSC_BOT_CBW_SIGNATURE;
|
||||
USBH_MSC_CBWData.field.CBWTag = HOST_MSC_BOT_CBW_TAG;
|
||||
USBH_MSC_CBWData.field.CBWLUN = 0U;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
}
|
||||
BOTStallErrorCount = 0UL;
|
||||
MSCErrorCount = 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief manages the different states of BOT transfer and updates the
|
||||
* status for the upper layer.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_msc_botxferprocess(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
uint8_t xferDirection, index;
|
||||
static uint32_t remainingDataLength;
|
||||
static uint8_t *datapointer, *datapointer_prev;
|
||||
static uint8_t error_direction;
|
||||
HOST_STATUS status;
|
||||
|
||||
HOST_CH_XFER_STATE URB_Status;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
|
||||
switch (USBH_MSC_BOTXferParam.BOTState) {
|
||||
case HOST_MSC_SEND_CBW:
|
||||
/* send a CBW */
|
||||
usb_host_sendbulkdata(pdev,
|
||||
&USBH_MSC_CBWData.CBWArray[0],
|
||||
HOST_MSC_BOT_CBW_PACKET_LENGTH,
|
||||
MSC_Machine.hc_num_out);
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_SEND_CBW;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SENT_CBW;
|
||||
break;
|
||||
case HOST_MSC_SENT_CBW:
|
||||
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_out);
|
||||
switch (URB_Status) {
|
||||
case HOST_CH_XFER_DONE:
|
||||
BOTStallErrorCount = 0U;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_SENT_CBW;
|
||||
/* If the CBW packet is sent successful, then update the state */
|
||||
xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK);
|
||||
if (USBH_MSC_CBWData.field.CBWTransferLength != 0UL) {
|
||||
remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ;
|
||||
datapointer = USBH_MSC_BOTXferParam.pRxTxBuff;
|
||||
datapointer_prev = datapointer;
|
||||
/* If there has data transfer stage, update the direction whether it is D2H or H2D */
|
||||
if (xferDirection == USB_D2H) {
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_DATAIN_STATE;
|
||||
} else {
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_DATAOUT_STATE;
|
||||
}
|
||||
} else {
|
||||
/* If there has not data transfer stage also update the state */
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
}
|
||||
break;
|
||||
case HOST_CH_XFER_UNREADY:
|
||||
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
|
||||
break;
|
||||
case HOST_CH_XFER_STALL:
|
||||
error_direction = HOST_MSC_DIR_OUT;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HOST_MSC_BOT_DATAIN_STATE:
|
||||
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_in);
|
||||
if ((URB_Status == HOST_CH_XFER_DONE) \
|
||||
|| (USBH_MSC_BOTXferParam.BOTStateBkp != HOST_MSC_BOT_DATAIN_STATE)) {
|
||||
BOTStallErrorCount = 0U;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_BOT_DATAIN_STATE;
|
||||
|
||||
if (remainingDataLength > MSC_Machine.MSC_BulkInEpSize) {
|
||||
usb_host_recvbulkdata(pdev,
|
||||
datapointer,
|
||||
MSC_Machine.MSC_BulkInEpSize,
|
||||
MSC_Machine.hc_num_in);
|
||||
remainingDataLength -= MSC_Machine.MSC_BulkInEpSize;
|
||||
datapointer = datapointer + MSC_Machine.MSC_BulkInEpSize;
|
||||
} else if (remainingDataLength == 0UL) {
|
||||
/* If value was 0, and successful transfer, then change the state */
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
} else {
|
||||
usb_host_recvbulkdata(pdev,
|
||||
datapointer,
|
||||
(uint16_t)remainingDataLength,
|
||||
MSC_Machine.hc_num_in);
|
||||
remainingDataLength = 0UL;
|
||||
}
|
||||
} else if (URB_Status == HOST_CH_XFER_STALL) {
|
||||
error_direction = HOST_MSC_DIR_IN;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_IN;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_BOT_DATAOUT_STATE:
|
||||
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_out);
|
||||
if (URB_Status == HOST_CH_XFER_DONE) {
|
||||
BOTStallErrorCount = 0UL;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_BOT_DATAOUT_STATE;
|
||||
if (remainingDataLength > MSC_Machine.MSC_BulkOutEpSize) {
|
||||
usb_host_sendbulkdata(pdev,
|
||||
datapointer,
|
||||
MSC_Machine.MSC_BulkOutEpSize,
|
||||
MSC_Machine.hc_num_out);
|
||||
datapointer_prev = datapointer;
|
||||
datapointer = datapointer + MSC_Machine.MSC_BulkOutEpSize;
|
||||
|
||||
remainingDataLength = remainingDataLength - MSC_Machine.MSC_BulkOutEpSize;
|
||||
} else if (remainingDataLength == 0UL) {
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
} else {
|
||||
usb_host_sendbulkdata(pdev,
|
||||
datapointer,
|
||||
(uint16_t)remainingDataLength,
|
||||
MSC_Machine.hc_num_out);
|
||||
remainingDataLength = 0UL;
|
||||
}
|
||||
} else if (URB_Status == HOST_CH_XFER_UNREADY) {
|
||||
if (datapointer != datapointer_prev) {
|
||||
usb_host_sendbulkdata(pdev,
|
||||
(datapointer - MSC_Machine.MSC_BulkOutEpSize),
|
||||
MSC_Machine.MSC_BulkOutEpSize,
|
||||
MSC_Machine.hc_num_out);
|
||||
} else {
|
||||
usb_host_sendbulkdata(pdev,
|
||||
datapointer,
|
||||
MSC_Machine.MSC_BulkOutEpSize,
|
||||
MSC_Machine.hc_num_out);
|
||||
}
|
||||
} else if (URB_Status == HOST_CH_XFER_STALL) {
|
||||
error_direction = HOST_MSC_DIR_OUT;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
case HOST_MSC_RECEIVE_CSW_STATE:
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
|
||||
USBH_MSC_BOTXferParam.DataLength = HOST_MSC_CSW_MAX_LENGTH;
|
||||
for (index = 0U; index < HOST_MSC_CSW_LENGTH; index++) {
|
||||
USBH_MSC_CSWData.CSWArray[index] = 0U;
|
||||
}
|
||||
|
||||
USBH_MSC_CSWData.CSWArray[0] = 0U;
|
||||
usb_host_recvbulkdata(pdev,
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff,
|
||||
HOST_MSC_CSW_MAX_LENGTH,
|
||||
MSC_Machine.hc_num_in);
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_DECODE_CSW;
|
||||
|
||||
break;
|
||||
|
||||
case HOST_MSC_DECODE_CSW:
|
||||
URB_Status = host_driver_getxferstate(pdev, MSC_Machine.hc_num_in);
|
||||
if (URB_Status == HOST_CH_XFER_DONE) {
|
||||
BOTStallErrorCount = 0UL;
|
||||
USBH_MSC_BOTXferParam.BOTStateBkp = HOST_MSC_RECEIVE_CSW_STATE;
|
||||
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = usb_host_msc_cswdecode(pdev, phost);
|
||||
} else if (URB_Status == HOST_CH_XFER_STALL) {
|
||||
error_direction = HOST_MSC_DIR_IN;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_IN;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
case HOST_MSC_BOT_ERROR_IN:
|
||||
status = usb_host_msc_botabort(pdev, phost, HOST_MSC_DIR_IN);
|
||||
if (status == HSTATUS_OK) {
|
||||
if (error_direction == HOST_MSC_BOTH_DIR) {
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_BOT_ERROR_OUT;
|
||||
} else {
|
||||
/* switch back to the original state */
|
||||
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
|
||||
}
|
||||
} else if (status == HSTATUS_UNRECOVERED_ERROR) {
|
||||
/* This means that there is a STALL Error limit, Do Reset Recovery */
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_PHASE_ERROR;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_BOT_ERROR_OUT:
|
||||
status = usb_host_msc_botabort(pdev, phost, HOST_MSC_DIR_OUT);
|
||||
if (status == HSTATUS_OK) {
|
||||
/* switch back to the original state */
|
||||
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
|
||||
} else if (status == HSTATUS_UNRECOVERED_ERROR) {
|
||||
/* This means that there is a STALL Error limit, Do Reset Recovery */
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_PHASE_ERROR;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief manages the different Error handling for STALL
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] direction IN / OUT
|
||||
* @retval None
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_botabort(usb_core_instance *pdev, USBH_HOST *phost, uint8_t direction)
|
||||
{
|
||||
HOST_STATUS status;
|
||||
|
||||
status = HSTATUS_BUSY;
|
||||
|
||||
switch (direction) {
|
||||
case HOST_MSC_DIR_IN:
|
||||
/* send ClrFeture on Bulk IN endpoint */
|
||||
status = usb_host_clrfeature(pdev,
|
||||
phost,
|
||||
MSC_Machine.MSC_BulkInEp,
|
||||
MSC_Machine.hc_num_in);
|
||||
break;
|
||||
case HOST_MSC_DIR_OUT:
|
||||
/* send ClrFeature on Bulk OUT endpoint */
|
||||
status = usb_host_clrfeature(pdev,
|
||||
phost,
|
||||
MSC_Machine.MSC_BulkOutEp,
|
||||
MSC_Machine.hc_num_out);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BOTStallErrorCount++;
|
||||
if (BOTStallErrorCount > 4UL) {
|
||||
status = HSTATUS_UNRECOVERED_ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes the CSW received by the device and updates the same to upper layer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval On success USB_HOST_MSC_OK, on failure USB_HOST_MSC_FAIL
|
||||
*/
|
||||
uint8_t usb_host_msc_cswdecode(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status;
|
||||
uint32_t dataXferCount;
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
dataXferCount = host_driver_getxfercnt(pdev, MSC_Machine.hc_num_in);
|
||||
if (dataXferCount != HOST_MSC_CSW_LENGTH) {
|
||||
/*(4) Hi > Dn (Host expects to receive data from the device,
|
||||
Device intends to transfer no data)
|
||||
(5) Hi > Di (Host expects to receive data from the device,
|
||||
Device intends to send data to the host)
|
||||
(9) Ho > Dn (Host expects to send data to the device,
|
||||
Device intends to transfer no data)
|
||||
(11) Ho > Do (Host expects to send data to the device,
|
||||
Device intends to receive data from the host)*/
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
} else {
|
||||
/* CSW length is Correct */
|
||||
|
||||
/* Check validity of the CSW Signature and CSWStatus */
|
||||
if (USBH_MSC_CSWData.field.dCSWSignature == HOST_MSC_BOT_CSW_SIGNATURE) {
|
||||
/* Check Condition 1. dCSWSignature is equal to 53425355h */
|
||||
if (USBH_MSC_CSWData.field.dCSWTag == USBH_MSC_CBWData.field.CBWTag) {
|
||||
/* Check Condition 3. dCSWTag matches the dCBWTag from the
|
||||
corresponding CBW */
|
||||
if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_OK) {
|
||||
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
|
||||
|
||||
Hn Host expects no data transfers
|
||||
Hi Host expects to receive data from the device
|
||||
Ho Host expects to send data to the device
|
||||
|
||||
Dn Device intends to transfer no data
|
||||
Di Device intends to send data to the host
|
||||
Do Device intends to receive data from the host
|
||||
|
||||
Section 6.7
|
||||
(1) Hn = Dn (Host expects no data transfers,
|
||||
Device intends to transfer no data)
|
||||
(6) Hi = Di (Host expects to receive data from the device,
|
||||
Device intends to send data to the host)
|
||||
(12) Ho = Do (Host expects to send data to the device,
|
||||
Device intends to receive data from the host)
|
||||
*/
|
||||
status = USB_HOST_MSC_OK;
|
||||
} else if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_FAIL) {
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
} else if (USBH_MSC_CSWData.field.dCSWStatus == (uint8_t)USB_HOST_MSC_PHASE_ERROR) {
|
||||
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
|
||||
Section 6.7
|
||||
(2) Hn < Di ( Host expects no data transfers,
|
||||
Device intends to send data to the host)
|
||||
(3) Hn < Do ( Host expects no data transfers,
|
||||
Device intends to receive data from the host)
|
||||
(7) Hi < Di ( Host expects to receive data from the device,
|
||||
Device intends to send data to the host)
|
||||
(8) Hi <> Do ( Host expects to receive data from the device,
|
||||
Device intends to receive data from the host)
|
||||
(10) Ho <> Di (Host expects to send data to the device,
|
||||
Di Device intends to send data to the host)
|
||||
(13) Ho < Do (Host expects to send data to the device,
|
||||
Device intends to receive data from the host)
|
||||
*/
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)status;
|
||||
return (uint8_t)status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_bot.h
|
||||
* @brief Head file for usb_host_msc_bot.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_MSC_BOT_H__
|
||||
#define __USB_HOST_MSC_BOT_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_stdreq.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
typedef union _USBH_CBW_Block {
|
||||
struct __CBW {
|
||||
uint32_t CBWSignature;
|
||||
uint32_t CBWTag;
|
||||
uint32_t CBWTransferLength;
|
||||
uint8_t CBWFlags;
|
||||
uint8_t CBWLUN;
|
||||
uint8_t CBWLength;
|
||||
uint8_t CBWCB[16];
|
||||
} field;
|
||||
uint8_t CBWArray[31];
|
||||
} HostCBWPkt_TypeDef;
|
||||
|
||||
typedef struct {
|
||||
uint8_t MSCState;
|
||||
uint8_t MSCStateBkp;
|
||||
uint8_t MSCStateCurrent;
|
||||
uint8_t CmdStateMachine;
|
||||
uint8_t BOTState;
|
||||
uint8_t BOTStateBkp;
|
||||
uint8_t *pRxTxBuff;
|
||||
uint16_t DataLength;
|
||||
uint8_t BOTXferStatus;
|
||||
} USB_HOST_BOTXFER_TypeDef;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t dCSWSignature;
|
||||
uint32_t dCSWTag;
|
||||
uint32_t dCSWDataResidue;
|
||||
uint8_t dCSWStatus;
|
||||
} field;
|
||||
uint8_t CSWArray[13];
|
||||
} HOST_CSW_PACKET_TypeDef;
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define HOST_MSC_BOT_INIT_STATE (0U)
|
||||
#define HOST_MSC_BOT_RESET (1U)
|
||||
#define HOST_MSC_GET_MAX_LUN (2U)
|
||||
#define HOST_MSC_TEST_UNIT_READY (3U)
|
||||
#define HOST_MSC_READ_CAPACITY10 (4U)
|
||||
#define HOST_MSC_MODE_SENSE6 (5U)
|
||||
#define HOST_MSC_REQUEST_SENSE (6U)
|
||||
#define HOST_MSC_BOT_USB_TRANSFERS (7U)
|
||||
#define HOST_MSC_DEFAULT_APPLI_STATE (8U)
|
||||
#define HOST_MSC_CTRL_ERROR_STATE (9U)
|
||||
#define HOST_MSC_UNRECOVERED_STATE (10U)
|
||||
|
||||
#define HOST_MSC_SEND_CBW (1U)
|
||||
#define HOST_MSC_SENT_CBW (2U)
|
||||
#define HOST_MSC_BOT_DATAIN_STATE (3U)
|
||||
#define HOST_MSC_BOT_DATAOUT_STATE (4U)
|
||||
#define HOST_MSC_RECEIVE_CSW_STATE (5U)
|
||||
#define HOST_MSC_DECODE_CSW (6U)
|
||||
#define HOST_MSC_BOT_ERROR_IN (7U)
|
||||
#define HOST_MSC_BOT_ERROR_OUT (8U)
|
||||
|
||||
#define HOST_MSC_BOT_CBW_SIGNATURE (0x43425355UL)
|
||||
#define HOST_MSC_BOT_CBW_TAG (0x20304050UL)
|
||||
#define HOST_MSC_BOT_CSW_SIGNATURE (0x53425355UL)
|
||||
#define HOST_MSC_CSW_DATA_LENGTH (13U)
|
||||
#define HOST_MSC_BOT_CBW_PACKET_LENGTH (31U)
|
||||
#define HOST_MSC_CSW_LENGTH (13U)
|
||||
#define HOST_MSC_CSW_MAX_LENGTH (63U)
|
||||
#define HOST_MSC_DIR_IN (0U)
|
||||
#define HOST_MSC_DIR_OUT (1U)
|
||||
#define HOST_MSC_BOTH_DIR (2U)
|
||||
#define HOST_MSC_PAGE_LENGTH (512UL)
|
||||
|
||||
#define CBW_CB_LENGTH (16U)
|
||||
#define CBW_LENGTH (10U)
|
||||
#define CBW_LENGTH_TEST_UNIT_READY (6U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
extern USB_HOST_BOTXFER_TypeDef USBH_MSC_BOTXferParam;
|
||||
extern HostCBWPkt_TypeDef USBH_MSC_CBWData;
|
||||
extern HOST_CSW_PACKET_TypeDef USBH_MSC_CSWData;
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void usb_host_msc_init(usb_core_instance *pdev);
|
||||
extern void usb_host_msc_botxferprocess(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
extern uint8_t usb_host_msc_cswdecode(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
extern HOST_STATUS usb_host_msc_botabort(usb_core_instance *pdev, USBH_HOST *phost, uint8_t direction);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_MSC_BOT_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_class.c
|
||||
* @brief The MSC class driver functions
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_msc_class.h"
|
||||
#include "usb_host_msc_scsi.h"
|
||||
#include "usb_host_msc_bot.h"
|
||||
#include "usb_host_core.h"
|
||||
#include "usb_host_driver.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define USBH_MSC_ERROR_RETRY_LIMIT (10U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
HOST_STATUS usb_host_msc_itfinit(usb_core_instance *pdev, void *phost);
|
||||
void usb_host_msc_itfdeinit(usb_core_instance *pdev);
|
||||
HOST_STATUS usb_host_msc_process(usb_core_instance *pdev, void *phost);
|
||||
HOST_STATUS usb_host_msc_classreq(usb_core_instance *pdev, void *phost);
|
||||
|
||||
HOST_STATUS usb_host_msc_bot_reset(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
HOST_STATUS usb_host_msc_maxlun_get(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
void usb_host_msc_error_process(USB_HOST_MSC_STATUS status);
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
#ifdef USB_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_INTERNAL_DMA_ENABLED */
|
||||
__USB_ALIGN_BEGIN MSC_Machine_TypeDef MSC_Machine;
|
||||
|
||||
#ifdef USB_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_INTERNAL_DMA_ENABLED */
|
||||
uint8_t MSCErrorCount = 0U;
|
||||
|
||||
usb_host_class_callback_func USBH_MSC_cb = {
|
||||
&usb_host_msc_itfinit,
|
||||
&usb_host_msc_itfdeinit,
|
||||
&usb_host_msc_classreq,
|
||||
&usb_host_msc_process,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief This request is used to issue a request to reset the msc device and
|
||||
* its related interface. This class-specific request shall prepare the
|
||||
* device for the next CBW from the host.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status define by HOST_STATUS
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_bot_reset(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
|
||||
USB_REQ_RECIPIENT_INTERFACE;
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_BOT_RESET;
|
||||
phost->ctrlparam.setup.b.wValue.w = 0U;
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0U;
|
||||
phost->ctrlparam.setup.b.wLength.w = 0U;
|
||||
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief this request is used to issue a request to get the max logic unit of
|
||||
* the msc device.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status defined by HOST_STATUS
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_maxlun_get(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
|
||||
USB_REQ_RECIPIENT_INTERFACE;
|
||||
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
|
||||
phost->ctrlparam.setup.b.wValue.w = 0U;
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0U;
|
||||
phost->ctrlparam.setup.b.wLength.w = 1U;
|
||||
return usb_host_ctrlreq(pdev, phost, MSC_Machine.buff, 1U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used for handling errors during processing the MSC
|
||||
* state machine
|
||||
* @param [in] status
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_msc_error_process(USB_HOST_MSC_STATUS status)
|
||||
{
|
||||
switch (status) {
|
||||
case USB_HOST_MSC_FAIL:
|
||||
MSCErrorCount++;
|
||||
if (MSCErrorCount < USBH_MSC_ERROR_RETRY_LIMIT) {
|
||||
/* Try MSC level error recovery, Issue the request Sense to get
|
||||
driver error reason */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_REQUEST_SENSE;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
} else {
|
||||
/* Error trials exceeded the limit, go to unrecovered state */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_UNRECOVERED_STATE;
|
||||
}
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
/* Phase error, Go to Unrecoovered state */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_UNRECOVERED_STATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interface initialization for msc class application, the channels for
|
||||
* the IN and OUT EP will be distributed.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status defined by HOST_STATUS
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_itfinit(usb_core_instance *pdev, void *phost)
|
||||
{
|
||||
USBH_HOST *pphost = phost;
|
||||
|
||||
if ((pphost->device_prop.devitfdesc[0].bInterfaceClass == MSC_CLASS) && \
|
||||
(pphost->device_prop.devitfdesc[0].bInterfaceProtocol == MSC_PROTOCOL)) {
|
||||
if ((pphost->device_prop.devepdesc[0][0].bEndpointAddress & 0x80U) == 0x80U) {
|
||||
MSC_Machine.MSC_BulkInEp = (pphost->device_prop.devepdesc[0][0].bEndpointAddress);
|
||||
MSC_Machine.MSC_BulkInEpSize = pphost->device_prop.devepdesc[0][0].wMaxPacketSize;
|
||||
} else {
|
||||
MSC_Machine.MSC_BulkOutEp = (pphost->device_prop.devepdesc[0][0].bEndpointAddress);
|
||||
MSC_Machine.MSC_BulkOutEpSize = pphost->device_prop.devepdesc[0] [0].wMaxPacketSize;
|
||||
}
|
||||
if ((pphost->device_prop.devepdesc[0][1].bEndpointAddress & 0x80U) == 0x80U) {
|
||||
MSC_Machine.MSC_BulkInEp = (pphost->device_prop.devepdesc[0][1].bEndpointAddress);
|
||||
MSC_Machine.MSC_BulkInEpSize = pphost->device_prop.devepdesc[0][1].wMaxPacketSize;
|
||||
} else {
|
||||
MSC_Machine.MSC_BulkOutEp = (pphost->device_prop.devepdesc[0][1].bEndpointAddress);
|
||||
MSC_Machine.MSC_BulkOutEpSize = pphost->device_prop.devepdesc[0][1].wMaxPacketSize;
|
||||
}
|
||||
/* distribute the channels for the EPs */
|
||||
MSC_Machine.hc_num_out = usb_host_distrch(pdev, MSC_Machine.MSC_BulkOutEp);
|
||||
MSC_Machine.hc_num_in = usb_host_distrch(pdev, MSC_Machine.MSC_BulkInEp);
|
||||
/* open the channels that have distributed */
|
||||
usb_host_chopen(pdev,
|
||||
MSC_Machine.hc_num_out,
|
||||
pphost->device_prop.devaddr,
|
||||
pphost->device_prop.devspeed,
|
||||
EP_TYPE_BULK,
|
||||
MSC_Machine.MSC_BulkOutEpSize);
|
||||
usb_host_chopen(pdev,
|
||||
MSC_Machine.hc_num_in,
|
||||
pphost->device_prop.devaddr,
|
||||
pphost->device_prop.devspeed,
|
||||
EP_TYPE_BULK,
|
||||
MSC_Machine.MSC_BulkInEpSize);
|
||||
} else {
|
||||
pphost->user_callbk->huser_devunsupported();
|
||||
}
|
||||
return HSTATUS_OK ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief deinitialize interface of msc class by freeing host channels
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_msc_itfdeinit(usb_core_instance *pdev)
|
||||
{
|
||||
if (MSC_Machine.hc_num_out != 0U) {
|
||||
usb_hchstop(&pdev->regs, MSC_Machine.hc_num_out);
|
||||
(void)usb_host_freech(pdev, MSC_Machine.hc_num_out);
|
||||
MSC_Machine.hc_num_out = 0U;
|
||||
}
|
||||
if (MSC_Machine.hc_num_in != 0U) {
|
||||
usb_hchstop(&pdev->regs, MSC_Machine.hc_num_in);
|
||||
(void)usb_host_freech(pdev, MSC_Machine.hc_num_in);
|
||||
MSC_Machine.hc_num_in = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize the msc state machine
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status defined by HOST_STATUS
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_classreq(usb_core_instance *pdev, void *phost)
|
||||
{
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_INIT_STATE;
|
||||
return HSTATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief process the msc state machine
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status defined by HOST_STATUS
|
||||
*/
|
||||
HOST_STATUS usb_host_msc_process(usb_core_instance *pdev, void *phost)
|
||||
{
|
||||
USBH_HOST *pphost = phost;
|
||||
HOST_STATUS status = HSTATUS_BUSY;
|
||||
USB_HOST_MSC_STATUS mscStatus;
|
||||
uint8_t appliStatus;
|
||||
static uint8_t maxLunExceed = FALSE;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.MSCState) {
|
||||
case HOST_MSC_BOT_INIT_STATE:
|
||||
usb_host_msc_init(pdev);
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_RESET;
|
||||
break;
|
||||
case HOST_MSC_BOT_RESET:
|
||||
/* issue a request to reset the bot. */
|
||||
status = usb_host_msc_bot_reset(pdev, phost);
|
||||
if (status == HSTATUS_OK) {
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_GET_MAX_LUN;
|
||||
}
|
||||
if (status == HSTATUS_UNSUPPORTED) {
|
||||
/* if the request fails, it needs to move to next state and should save the next state as backup */
|
||||
USBH_MSC_BOTXferParam.MSCStateBkp = HOST_MSC_GET_MAX_LUN;
|
||||
/* a clear feature should be issued if the request fails. */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_CTRL_ERROR_STATE;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_GET_MAX_LUN:
|
||||
/* issue a request to get the max logical unit(MAXLUN). */
|
||||
status = usb_host_msc_maxlun_get(pdev, phost);
|
||||
if (status == HSTATUS_OK) {
|
||||
MSC_Machine.maxLun = *(MSC_Machine.buff) ;
|
||||
if ((MSC_Machine.maxLun > 0U) && (maxLunExceed == FALSE)) {
|
||||
maxLunExceed = TRUE;
|
||||
pphost->user_callbk->huser_devunsupported();
|
||||
break;
|
||||
}
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_TEST_UNIT_READY;
|
||||
}
|
||||
|
||||
if (status == HSTATUS_UNSUPPORTED) {
|
||||
/* if the request fails, it needs to move to next state and should save the next state as backup */
|
||||
USBH_MSC_BOTXferParam.MSCStateBkp = HOST_MSC_TEST_UNIT_READY;
|
||||
/* a clear feature should be issued if the request fails. */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_CTRL_ERROR_STATE;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_CTRL_ERROR_STATE:
|
||||
/* issue a request to clear feature */
|
||||
status = usb_host_clrfeature(pdev,
|
||||
phost,
|
||||
0x00U,
|
||||
pphost->ctrlparam.hc_num_out);
|
||||
if (status == HSTATUS_OK) {
|
||||
/* If GetMaxLun Request not support, assume Single LUN configuration */
|
||||
MSC_Machine.maxLun = 0U;
|
||||
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_TEST_UNIT_READY:
|
||||
/* issue the request Test Unit Ready[0] of SCSI command */
|
||||
mscStatus = usb_host_msc_TestUnitReady(pdev);
|
||||
|
||||
if (mscStatus == USB_HOST_MSC_OK) {
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_READ_CAPACITY10;
|
||||
MSCErrorCount = 0U;
|
||||
status = HSTATUS_OK;
|
||||
} else {
|
||||
usb_host_msc_error_process(mscStatus);
|
||||
}
|
||||
break;
|
||||
|
||||
case HOST_MSC_READ_CAPACITY10:
|
||||
/* issue the request Read Capacity[0] of SCSI command. */
|
||||
mscStatus = usb_host_msc_ReadCapacity10(pdev);
|
||||
if (mscStatus == USB_HOST_MSC_OK) {
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_MODE_SENSE6;
|
||||
MSCErrorCount = 0U;
|
||||
status = HSTATUS_OK;
|
||||
} else {
|
||||
usb_host_msc_error_process(mscStatus);
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_MODE_SENSE6:
|
||||
/* issue the request ModeSense6 of SCSI command for detecting whelth the deviec is write-protected. */
|
||||
mscStatus = usb_host_msc_ModeSense6(pdev);
|
||||
if (mscStatus == USB_HOST_MSC_OK) {
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_DEFAULT_APPLI_STATE;
|
||||
MSCErrorCount = 0U;
|
||||
status = HSTATUS_OK;
|
||||
} else {
|
||||
usb_host_msc_error_process(mscStatus);
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_REQUEST_SENSE:
|
||||
/* issue the request RequestSense of SCSI command for retreiving error code. */
|
||||
mscStatus = usb_host_msc_RequestSense(pdev);
|
||||
if (mscStatus == USB_HOST_MSC_OK) {
|
||||
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
|
||||
status = HSTATUS_OK;
|
||||
} else {
|
||||
usb_host_msc_error_process(mscStatus);
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_BOT_USB_TRANSFERS:
|
||||
/* handle the BOT state machine. */
|
||||
usb_host_msc_botxferprocess(pdev, phost);
|
||||
break;
|
||||
case HOST_MSC_DEFAULT_APPLI_STATE:
|
||||
/* handle the user callback for the msc application. */
|
||||
appliStatus = pphost->user_callbk->huser_application();
|
||||
if (appliStatus == 0U) {
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_DEFAULT_APPLI_STATE;
|
||||
} else if (appliStatus == 1U) {
|
||||
/* deinit requested from the application layer. */
|
||||
status = HSTATUS_APP_DEINIT;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
break;
|
||||
case HOST_MSC_UNRECOVERED_STATE:
|
||||
status = HSTATUS_UNRECOVERED_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_class.h
|
||||
* @brief Head file for usb_host_msc_class.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_MSC_CLASS_H__
|
||||
#define __USB_HOST_MSC_CLASS_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_core.h"
|
||||
#include "usb_host_stdreq.h"
|
||||
#include "usb_bsp.h"
|
||||
#include "usb_host_ctrltrans.h"
|
||||
#include "usb_host_cfgch.h"
|
||||
#include "usb_host_msc_class.h"
|
||||
#include "usb_host_msc_scsi.h"
|
||||
#include "usb_host_msc_bot.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/* Structure for MSC process */
|
||||
typedef struct {
|
||||
uint8_t hc_num_in;
|
||||
uint8_t hc_num_out;
|
||||
uint8_t MSC_BulkOutEp;
|
||||
uint8_t MSC_BulkInEp;
|
||||
uint16_t MSC_BulkInEpSize;
|
||||
uint16_t MSC_BulkOutEpSize;
|
||||
uint8_t buff[USBH_MSC_MPS_SIZE];
|
||||
uint8_t maxLun;
|
||||
} MSC_Machine_TypeDef;
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define USB_REQ_BOT_RESET (0xFFU)
|
||||
#define USB_REQ_GET_MAX_LUN (0xFEU)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
extern usb_host_class_callback_func USBH_MSC_cb;
|
||||
extern MSC_Machine_TypeDef MSC_Machine;
|
||||
extern uint8_t MSCErrorCount;
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_MSC_CLASS_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_fatfs.c
|
||||
* @brief The fatfs functions.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_app_conf.h"
|
||||
#include "usb_host_driver.h"
|
||||
#ifdef USB_MSC_FAT_VALID
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
#include "usb_host_msc_class.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
extern usb_core_instance usb_app_instance;
|
||||
extern USBH_HOST usb_app_host;
|
||||
|
||||
/**
|
||||
* @brief Initialize Disk Drive
|
||||
* @param [in] drv Physical drive number (0)
|
||||
* @retval DSTATUS
|
||||
*/
|
||||
DSTATUS disk_initialize(BYTE drv)
|
||||
{
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
|
||||
Stat &= (DSTATUS)~STA_NOINIT;
|
||||
}
|
||||
return Stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Disk Status
|
||||
* @param [in] drv Physical drive number (0)
|
||||
* @retval DSTATUS
|
||||
*/
|
||||
DSTATUS disk_status(BYTE drv)
|
||||
{
|
||||
DSTATUS status = Stat;
|
||||
if (drv != 0U) {
|
||||
status = STA_NOINIT; /* Supports only single drive */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Sector(s)
|
||||
* @param [in] drv Physical drive number (0)
|
||||
* @param [in] buff Pointer to the data buffer to store read data
|
||||
* @param [in] sector Start sector number (LBA)
|
||||
* @param [in] count Sector count (1..255)
|
||||
* @retval DSTATUS
|
||||
*/
|
||||
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
|
||||
|
||||
if ((pdrv != 0U) || (count == 0UL)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if ((Stat & STA_NOINIT) == STA_NOINIT) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
|
||||
|
||||
do {
|
||||
status = usb_host_msc_Read10(&usb_app_instance, buff, sector, 512UL * (uint32_t)count);
|
||||
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
} while (status == USB_HOST_MSC_BUSY);
|
||||
}
|
||||
|
||||
if (status == USB_HOST_MSC_OK) {
|
||||
return RES_OK;
|
||||
}
|
||||
return RES_ERROR;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if _READONLY == 0
|
||||
/**
|
||||
* @brief Write Sector(s)
|
||||
* @param [in] drv Physical drive number (0)
|
||||
* @param [in] buff Pointer to the data to be written
|
||||
* @param [in] sector Start sector number (LBA)
|
||||
* @param [in] count Sector count (1..255)
|
||||
* @retval DSTATUS
|
||||
*/
|
||||
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_OK;
|
||||
|
||||
if ((pdrv != 0U) || (count == 0UL)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if ((Stat & STA_NOINIT) == STA_NOINIT) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
if ((Stat & STA_PROTECT) == STA_PROTECT) {
|
||||
return RES_WRPRT;
|
||||
}
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) != 0UL) {
|
||||
do {
|
||||
status = usb_host_msc_Write10(&usb_app_instance, (BYTE *)buff, sector, 512UL * (uint32_t)count);
|
||||
usb_host_msc_botxferprocess(&usb_app_instance, &usb_app_host);
|
||||
|
||||
if (host_driver_ifdevconnected(&usb_app_instance) == 0UL) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
} while (status == USB_HOST_MSC_BUSY);
|
||||
}
|
||||
|
||||
if (status == USB_HOST_MSC_OK) {
|
||||
return RES_OK;
|
||||
}
|
||||
return RES_ERROR;
|
||||
}
|
||||
#endif /* _READONLY == 0 */
|
||||
|
||||
//#if _USE_IOCTL != 0
|
||||
/**
|
||||
* @brief Miscellaneous Functions
|
||||
* @param [in] drv Physical drive number (0)
|
||||
* @param [in] ctrl Control code
|
||||
* @param [in] buff Buffer to send/receive control data
|
||||
**
|
||||
* @retval DSTATUS
|
||||
*/
|
||||
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
|
||||
{
|
||||
DRESULT res;
|
||||
|
||||
if (pdrv != 0U) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
res = RES_ERROR;
|
||||
|
||||
if ((Stat & STA_NOINIT) == STA_NOINIT) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case CTRL_SYNC : /* Make sure that no pending write process */
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
||||
*(DWORD *)buff = (DWORD) USB_HOST_MSC_Param.MSC_Capacity;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
|
||||
*(WORD *)buff = 512U;
|
||||
res = RES_OK;
|
||||
break;
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
||||
*(DWORD *)buff = 512UL;
|
||||
break;
|
||||
default:
|
||||
res = RES_PARERR;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//#endif
|
||||
#endif /* _USE_IOCTL != 0 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,528 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_scsi.c
|
||||
* @brief The SCSI commands。
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_msc_class.h"
|
||||
#include "usb_host_msc_scsi.h"
|
||||
#include "usb_host_msc_bot.h"
|
||||
#include "usb_host_ctrltrans.h"
|
||||
#include "usb_host_def.h"
|
||||
#include "usb_host_driver.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
MSC_PARAMETER USB_HOST_MSC_Param;
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
#ifdef USB_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ )
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif
|
||||
__USB_ALIGN_BEGIN static uint8_t USB_HOST_DataInBuf[512];
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Issues 'Test Unit Ready' command to the device. Once the response
|
||||
* received, it updates the status to upper layer, the length of the
|
||||
* command are 31bytes.
|
||||
* @param [in] pdev device instance
|
||||
* @retval status define by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_TestUnitReady(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t index;
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = 0UL;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY;
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
|
||||
USBH_MSC_BOTXferParam.DataLength = HOST_MSC_CSW_MAX_LENGTH;
|
||||
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_TEST_UNIT_READY;
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_TEST_UNIT_READY;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
/* Start the transfer, then let the state machine magage the other transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
/* Commands successfully sent and Response Received */
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue the 'Read capacity10' command to the device. Once the response
|
||||
* received, it updates the status to upper layer
|
||||
* @param [in] pdev device instance
|
||||
* @retval status define by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_ReadCapacity10(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t index;
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
/*Prepare the CBW and relevent field*/
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
|
||||
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_READ_CAPACITY10;
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ_CAPACITY10;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
/* Start the transfer, then let the state machine manage the other
|
||||
transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
/*assign the capacity*/
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[3]) = USB_HOST_DataInBuf[0];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[2]) = USB_HOST_DataInBuf[1];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[1]) = USB_HOST_DataInBuf[2];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Capacity)[0]) = USB_HOST_DataInBuf[3];
|
||||
/*assign the page length*/
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_PageLength)[1]) = USB_HOST_DataInBuf[6];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_PageLength)[0]) = USB_HOST_DataInBuf[7];
|
||||
/* Commands successfully sent and Response Received */
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue the 'Mode Sense6' Command to the device. This function is used
|
||||
* for reading the WriteProtect Status of the MSC device.
|
||||
* @param [in] pdev device instance
|
||||
* @retval status by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_ModeSense6(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t index;
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
/*Prepare the CBW and relevent field*/
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
|
||||
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
|
||||
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_MODE_SENSE6;
|
||||
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_MODE_SENSE6;
|
||||
USBH_MSC_CBWData.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | \
|
||||
MODE_SENSE_PAGE_CODE;
|
||||
|
||||
USBH_MSC_CBWData.field.CBWCB[4] = XFER_LEN_MODE_SENSE6;
|
||||
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
|
||||
/* Start the transfer, then let the state machine manage the other
|
||||
transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
/* Assign the Write Protect status */
|
||||
/* If WriteProtect = 0, Writing is allowed
|
||||
If WriteProtect != 0, Disk is Write Protected */
|
||||
if (0U != (USB_HOST_DataInBuf[2] & MASK_MODE_SENSE_WRITE_PROTECT)) {
|
||||
USB_HOST_MSC_Param.MSC_WriteProtect = DISK_WRITE_PROTECTED;
|
||||
} else {
|
||||
USB_HOST_MSC_Param.MSC_WriteProtect = 0U;
|
||||
}
|
||||
|
||||
/* Commands successfully sent and Response Received */
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_host_msc_RequestSense
|
||||
* Issues the Request Sense command to the device. Once the response
|
||||
* received, it updates the status to upper layer
|
||||
* @param [in] pdev device instance
|
||||
* @retval status defined by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_RequestSense(usb_core_instance *pdev)
|
||||
{
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
uint8_t index;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
/*Prepare the CBW and relevent field*/
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = \
|
||||
ALLOCATION_LENGTH_REQUEST_SENSE;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
|
||||
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = USB_HOST_DataInBuf;
|
||||
USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent;
|
||||
USBH_MSC_BOTXferParam.MSCStateCurrent = HOST_MSC_REQUEST_SENSE;
|
||||
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_REQUEST_SENSE;
|
||||
USBH_MSC_CBWData.field.CBWCB[1] = DESC_REQUEST_SENSE;
|
||||
USBH_MSC_CBWData.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE;
|
||||
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
/* Start the transfer, then let the state machine magage
|
||||
the other transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
/* Get Sense data*/
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[3]) = USB_HOST_DataInBuf[0];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[2]) = USB_HOST_DataInBuf[1];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[1]) = USB_HOST_DataInBuf[2];
|
||||
(((uint8_t *)&USB_HOST_MSC_Param.MSC_Sense)[0]) = USB_HOST_DataInBuf[3];
|
||||
|
||||
/* Commands successfully sent and Response Received */
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_FAIL;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue the 'Write10 ' command to the device. Once the response received,
|
||||
* it updates the status to upper layer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] dataBuffer data buffer contains the data to write
|
||||
* @param [in] address address to which the data will be written
|
||||
* @param [in] nbOfbytes NbOfbytes to be written
|
||||
* @retval status define by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_Write10(usb_core_instance *pdev,
|
||||
uint8_t *dataBuffer,
|
||||
uint32_t address,
|
||||
uint32_t nbOfbytes)
|
||||
{
|
||||
uint8_t index;
|
||||
USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
uint16_t nbOfPages;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
|
||||
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_WRITE10;
|
||||
/*logical block address*/
|
||||
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t *)&address)[3]) ;
|
||||
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t *)&address)[2]);
|
||||
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t *)&address)[1]);
|
||||
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t *)&address)[0]);
|
||||
|
||||
/*HOST_MSC_PAGE_LENGTH = 512*/
|
||||
nbOfPages = (uint16_t)(nbOfbytes / HOST_MSC_PAGE_LENGTH);
|
||||
|
||||
/*Tranfer length */
|
||||
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
|
||||
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
|
||||
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
/* Start the transfer, then let the state machine
|
||||
magage the other transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue the read command to the device. Once the response received,
|
||||
* it updates the status to upper layer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] dataBuffer data buffer will contain the data to be read
|
||||
* @param [in] address Address from which the data will be read
|
||||
* @param [in] nbOfbytes number of bytes to be read
|
||||
* @retval status defined by USB_HOST_MSC_STATUS
|
||||
*/
|
||||
USB_HOST_MSC_STATUS usb_host_msc_Read10(usb_core_instance *pdev,
|
||||
uint8_t *dataBuffer,
|
||||
uint32_t address,
|
||||
uint32_t nbOfbytes)
|
||||
{
|
||||
uint8_t index;
|
||||
static USB_HOST_MSC_STATUS status = USB_HOST_MSC_BUSY;
|
||||
uint16_t nbOfPages;
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
|
||||
if (host_driver_ifdevconnected(pdev) != 0UL) {
|
||||
switch (USBH_MSC_BOTXferParam.CmdStateMachine) {
|
||||
case USB_HOST_MSC_CMD_SEND:
|
||||
/*Prepare the CBW and relevent field*/
|
||||
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
|
||||
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
|
||||
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
|
||||
|
||||
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
|
||||
|
||||
for (index = 0U; index < CBW_CB_LENGTH; index++) {
|
||||
USBH_MSC_CBWData.field.CBWCB[index] = 0x00U;
|
||||
}
|
||||
|
||||
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ10;
|
||||
|
||||
/*logical block address*/
|
||||
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t *)&address)[3]);
|
||||
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t *)&address)[2]);
|
||||
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t *)&address)[1]);
|
||||
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t *)&address)[0]);
|
||||
/*HOST_MSC_PAGE_LENGTH = 512*/
|
||||
nbOfPages = (uint16_t)(nbOfbytes / HOST_MSC_PAGE_LENGTH);
|
||||
/*Tranfer length */
|
||||
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
|
||||
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
|
||||
USBH_MSC_BOTXferParam.BOTState = HOST_MSC_SEND_CBW;
|
||||
/* Start the transfer, then let the state machine
|
||||
magage the other transactions */
|
||||
USBH_MSC_BOTXferParam.MSCState = HOST_MSC_BOT_USB_TRANSFERS;
|
||||
USBH_MSC_BOTXferParam.BOTXferStatus = (uint8_t)USB_HOST_MSC_BUSY;
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_WAIT;
|
||||
status = USB_HOST_MSC_BUSY;
|
||||
break;
|
||||
|
||||
case USB_HOST_MSC_CMD_WAIT:
|
||||
switch (USBH_MSC_BOTXferParam.BOTXferStatus) {
|
||||
case USB_HOST_MSC_OK:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_OK;
|
||||
break;
|
||||
case USB_HOST_MSC_FAIL:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
break;
|
||||
case USB_HOST_MSC_PHASE_ERROR:
|
||||
USBH_MSC_BOTXferParam.CmdStateMachine = USB_HOST_MSC_CMD_SEND;
|
||||
status = USB_HOST_MSC_PHASE_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_msc_scsi.h
|
||||
* @brief Head file for usb_host_msc_scsi.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_MSC_SCSI_H__
|
||||
#define __USB_HOST_MSC_SCSI_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_stdreq.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CLASS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/* USBH_MSC_SCSI_Exported_Types */
|
||||
typedef enum {
|
||||
USB_HOST_MSC_OK = 0U,
|
||||
USB_HOST_MSC_FAIL,
|
||||
USB_HOST_MSC_PHASE_ERROR,
|
||||
USB_HOST_MSC_BUSY
|
||||
} USB_HOST_MSC_STATUS;
|
||||
|
||||
typedef struct {
|
||||
uint32_t MSC_Capacity;
|
||||
uint32_t MSC_Sense;
|
||||
uint16_t MSC_PageLength;
|
||||
uint8_t MSC_BulkOutEP;
|
||||
uint8_t MSC_BulkInEP;
|
||||
uint8_t MSC_WriteProtect;
|
||||
} MSC_PARAMETER;
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define USB_HOST_MSC_CMD_SEND (1)
|
||||
#define USB_HOST_MSC_CMD_WAIT (2)
|
||||
|
||||
#define OPCODE_TEST_UNIT_READY (0x00U)
|
||||
#define OPCODE_READ_CAPACITY10 (0x25U)
|
||||
#define OPCODE_MODE_SENSE6 (0x1AU)
|
||||
#define OPCODE_READ10 (0x28U)
|
||||
#define OPCODE_WRITE10 (0x2AU)
|
||||
#define OPCODE_REQUEST_SENSE (0x03U)
|
||||
|
||||
#define DESC_REQUEST_SENSE (0x00U)
|
||||
#define ALLOCATION_LENGTH_REQUEST_SENSE (63U)
|
||||
#define XFER_LEN_READ_CAPACITY10 (8U)
|
||||
#define XFER_LEN_MODE_SENSE6 (63U)
|
||||
|
||||
#define MASK_MODE_SENSE_WRITE_PROTECT (0x80U)
|
||||
#define MODE_SENSE_PAGE_CONTROL_FIELD (0x00U)
|
||||
#define MODE_SENSE_PAGE_CODE (0x3FU)
|
||||
#define DISK_WRITE_PROTECTED (0x01U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
extern MSC_PARAMETER USB_HOST_MSC_Param;
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_TestUnitReady(usb_core_instance *pdev);
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_ReadCapacity10(usb_core_instance *pdev);
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_ModeSense6(usb_core_instance *pdev);
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_RequestSense(usb_core_instance *pdev);
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_Write10(usb_core_instance *pdev,
|
||||
uint8_t *dataBuffer,
|
||||
uint32_t address,
|
||||
uint32_t nbOfbytes);
|
||||
extern USB_HOST_MSC_STATUS usb_host_msc_Read10(usb_core_instance *pdev,
|
||||
uint8_t *dataBuffer,
|
||||
uint32_t address,
|
||||
uint32_t nbOfbytes);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_MSC_SCSI_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SRC_FILES := usb_host_cfgch.c usb_host_core.c usb_host_ctrltrans.c usb_host_driver.c usb_host_int.c usb_host_stdreq.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_cfgch.c
|
||||
* @brief Functions for opening and closing host channels
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_cfgch.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE LL USB Host Core
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
uint16_t usb_host_getfreech(usb_core_instance *pdev);
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief configure and open a pipe
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] hc_num host channel index
|
||||
* @param [in] dev_address USB Device address allocated to attached device
|
||||
* @param [in] speed core speed
|
||||
* @param [in] ep_type communication type of the EP
|
||||
* @param [in] mps max size of the packet
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_chopen(usb_core_instance *pdev,
|
||||
uint8_t hc_num,
|
||||
uint8_t dev_address,
|
||||
uint8_t speed,
|
||||
uint8_t ep_type,
|
||||
uint16_t mps)
|
||||
{
|
||||
pdev->host.hc[hc_num].ep_idx = (uint8_t) pdev->host.channel[hc_num] & 0x7Fu;
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)((pdev->host.channel[hc_num] & 0x80U) == 0x80U);
|
||||
pdev->host.hc[hc_num].dev_addr = dev_address;
|
||||
pdev->host.hc[hc_num].ep_type = ep_type;
|
||||
pdev->host.hc[hc_num].max_packet = mps;
|
||||
pdev->host.hc[hc_num].ch_speed = speed;
|
||||
pdev->host.hc[hc_num].in_toggle = 0U;
|
||||
pdev->host.hc[hc_num].out_toggle = 0U;
|
||||
|
||||
(void)usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief change a pipe on host
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] hc_num host channel index
|
||||
* @param [in] dev_address USB Device address allocated to attached device
|
||||
* @param [in] speed core speed
|
||||
* @param [in] ep_type communication type of EP
|
||||
* @param [in] mps max size of packet
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_mdfch(usb_core_instance *pdev,
|
||||
uint8_t hc_num,
|
||||
uint8_t dev_address,
|
||||
uint8_t speed,
|
||||
uint8_t ep_type,
|
||||
uint16_t mps)
|
||||
{
|
||||
(void)(ep_type);
|
||||
if (dev_address != 0U) {
|
||||
pdev->host.hc[hc_num].dev_addr = dev_address;
|
||||
}
|
||||
if ((pdev->host.hc[hc_num].max_packet != mps) && (mps != 0U)) {
|
||||
pdev->host.hc[hc_num].max_packet = mps;
|
||||
}
|
||||
if ((pdev->host.hc[hc_num].ch_speed != speed) && (speed != 0U)) {
|
||||
pdev->host.hc[hc_num].ch_speed = speed;
|
||||
}
|
||||
|
||||
(void)usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief distribute a new channel for the pipe
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ep_addr EP index the channel distributed for
|
||||
* @retval hc_num host channel index
|
||||
*/
|
||||
uint8_t usb_host_distrch(usb_core_instance *pdev, uint8_t ep_addr)
|
||||
{
|
||||
__IO uint16_t hc_num;
|
||||
|
||||
hc_num = usb_host_getfreech(pdev);
|
||||
if (hc_num != HC_ERROR) {
|
||||
pdev->host.channel[hc_num & (USB_MAX_TX_FIFOS - 1U)] = HC_USED | ep_addr;
|
||||
}
|
||||
return (uint8_t)hc_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free the USB host channel assigned by idx
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] idx Channel number to be freed
|
||||
* @retval Status
|
||||
*/
|
||||
uint8_t usb_host_freech(usb_core_instance *pdev, uint8_t idx)
|
||||
{
|
||||
if (idx < MAX_CHNUM) {
|
||||
pdev->host.channel[idx & (USB_MAX_TX_FIFOS - 1U)] &= HC_USED_MASK;
|
||||
}
|
||||
return (uint8_t)HSTATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free all the USB host channels
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_dedistrallch(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t idx;
|
||||
|
||||
for (idx = 2U; idx < MAX_CHNUM ; idx ++) {
|
||||
pdev->host.channel[idx & (USB_MAX_TX_FIFOS - 1U)] = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a free channel number so that can be distributed to a device endpoint
|
||||
* @param [in] pdev device instance
|
||||
* @retval idx the free channel index
|
||||
*/
|
||||
uint16_t usb_host_getfreech(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t tmp_idx;
|
||||
uint16_t u16Ret = HC_ERROR;
|
||||
|
||||
for (tmp_idx = 0U ; tmp_idx < MAX_CHNUM ; tmp_idx++) {
|
||||
if ((pdev->host.channel[tmp_idx & (USB_MAX_TX_FIFOS - 1U)] & HC_USED) == 0U) {
|
||||
u16Ret = HC_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (u16Ret == HC_OK) {
|
||||
u16Ret = tmp_idx;
|
||||
} else {
|
||||
u16Ret = HC_ERROR;
|
||||
}
|
||||
|
||||
return u16Ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_cfgch.h
|
||||
* @brief header file for the usb_host_cfgch.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_CFGCH_H__
|
||||
#define __USB_HOST_CFGCH_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/* USBH_HCS_Exported_Defines */
|
||||
#define MAX_CHNUM (12U)
|
||||
|
||||
#define HC_OK (0x0000U)
|
||||
#define HC_USED (0x8000U)
|
||||
#define HC_ERROR (0xFFFFU)
|
||||
#define HC_USED_MASK (0x7FFFU)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern uint8_t usb_host_distrch(usb_core_instance *pdev, uint8_t ep_addr);
|
||||
|
||||
extern uint8_t usb_host_freech(usb_core_instance *pdev, uint8_t idx);
|
||||
|
||||
extern void usb_host_dedistrallch(usb_core_instance *pdev);
|
||||
|
||||
extern void usb_host_chopen(usb_core_instance *pdev,
|
||||
uint8_t hc_num,
|
||||
uint8_t dev_address,
|
||||
uint8_t speed,
|
||||
uint8_t ep_type,
|
||||
uint16_t mps);
|
||||
|
||||
extern void usb_host_mdfch(usb_core_instance *pdev,
|
||||
uint8_t hc_num,
|
||||
uint8_t dev_address,
|
||||
uint8_t speed,
|
||||
uint8_t ep_type,
|
||||
uint16_t mps);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_CFGCH_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,537 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_core.c
|
||||
* @brief The core state machine process the enumeration and the control transfer process
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "usb_host_core.h"
|
||||
#include "usb_host_cfgch.h"
|
||||
#include "usb_host_ctrltrans.h"
|
||||
#include "usb_host_driver.h"
|
||||
#include "usb_host_stdreq.h"
|
||||
#include "usb_host_int.h"
|
||||
#include "usb_bsp.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
HOST_STATUS usb_host_ctrlprocess(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
HOST_STATUS usb_host_enumprocess(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
static uint8_t Local_Buffer[ENUM_LOCAL_BUF];
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief initialization for the host application
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] class_cbk the call back function for the class application
|
||||
* @param [in] user_cbk the call back function for user
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_init(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
usb_host_class_callback_func *class_cbk,
|
||||
usb_host_user_callback_func *user_cbk)
|
||||
{
|
||||
usb_bsp_init(pdev);
|
||||
usb_host_deinit(pdev, phost);
|
||||
phost->class_callbk = class_cbk;
|
||||
phost->user_callbk = user_cbk;
|
||||
host_driver_init(pdev);
|
||||
phost->user_callbk->huser_init();
|
||||
usb_bsp_nvicconfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief deinitialize the host application
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_deinit(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
phost->host_state = HOST_IDLE;
|
||||
phost->host_state_backup = HOST_IDLE;
|
||||
phost->enum_state = ENUM_IDLE;
|
||||
phost->req_state = REQ_CMD_TX;
|
||||
|
||||
phost->ctrlparam.ctrl_state = CTRL_SETUP;
|
||||
phost->ctrlparam.ctrlmaxsize = USB_MAX_EP0_SIZE;
|
||||
|
||||
phost->device_prop.devaddr = DEV_DEFAULT_ADDRESS;
|
||||
phost->device_prop.devspeed = PRTSPD_FULL_SPEED;
|
||||
|
||||
(void)usb_host_freech(pdev, phost->ctrlparam.hc_num_in);
|
||||
(void)usb_host_freech(pdev, phost->ctrlparam.hc_num_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This is the main process function for the host core, it will process
|
||||
* the main machine, such as connect,disconnect, emunation etc.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_mainprocess(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
__IO HOST_STATUS tmp_status;
|
||||
tmp_status = HSTATUS_FAIL;
|
||||
HOST_HANDLE_STATE tmp_host_state;
|
||||
|
||||
if ((host_driver_ifdevconnected(pdev) == 0UL) && (phost->host_state != HOST_IDLE)) {
|
||||
if (phost->host_state != HOST_DEV_DISCONNECTED) {
|
||||
phost->host_state = HOST_DEV_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if ((host_driver_ifdevconnected(pdev) == 0UL) && (phost->host_state == HOST_IDLE)
|
||||
&& (host_driver_getvbusdrivestate(pdev) == 0UL)) {
|
||||
phost->host_state = HOST_DEV_DISCONNECTED;
|
||||
}
|
||||
|
||||
tmp_host_state = phost->host_state;
|
||||
if (tmp_host_state == HOST_IDLE) {
|
||||
if (0U != host_driver_ifdevconnected(pdev)) {
|
||||
phost->host_state = HOST_DEV_CONNECTED;
|
||||
usb_mdelay(50UL);
|
||||
}
|
||||
} else if (tmp_host_state == HOST_DEV_CONNECTED) {
|
||||
#ifdef MSC_HID_COMPOSITE
|
||||
if (host_driver_getcurrentspd(pdev) == 2) {
|
||||
host_driver_init(pdev);
|
||||
}
|
||||
#endif /* MSC_HID_COMPOSITE */
|
||||
phost->user_callbk->huser_devattached();
|
||||
phost->ctrlparam.hc_num_out = usb_host_distrch(pdev, 0x00U);
|
||||
phost->ctrlparam.hc_num_in = usb_host_distrch(pdev, 0x80U);
|
||||
host_driver_portrst(pdev);
|
||||
phost->user_callbk->huser_devreset();
|
||||
phost->device_prop.devspeed = (uint8_t)host_driver_getcurrentspd(pdev);
|
||||
phost->host_state = HOST_ENUM;
|
||||
phost->user_callbk->huser_devspddetected(phost->device_prop.devspeed);
|
||||
usb_host_chopen(pdev,
|
||||
phost->ctrlparam.hc_num_in,
|
||||
phost->device_prop.devaddr,
|
||||
phost->device_prop.devspeed,
|
||||
EP_TYPE_CTRL,
|
||||
(uint16_t)phost->ctrlparam.ctrlmaxsize);
|
||||
usb_host_chopen(pdev,
|
||||
phost->ctrlparam.hc_num_out,
|
||||
phost->device_prop.devaddr,
|
||||
phost->device_prop.devspeed,
|
||||
EP_TYPE_CTRL,
|
||||
(uint16_t)phost->ctrlparam.ctrlmaxsize);
|
||||
} else if (tmp_host_state == HOST_ENUM) {
|
||||
if (usb_host_enumprocess(pdev, phost) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_enumcompl();
|
||||
phost->host_state = HOST_USER_INPUT;
|
||||
}
|
||||
} else if (tmp_host_state == HOST_USER_INPUT) {
|
||||
if ((phost->class_callbk->host_class_init(pdev, phost)) == HSTATUS_OK) {
|
||||
phost->host_state = HOST_CLASS_REQ;
|
||||
}
|
||||
} else if (tmp_host_state == HOST_CLASS_REQ) {
|
||||
tmp_status = phost->class_callbk->host_class_request(pdev, phost);
|
||||
if (tmp_status == HSTATUS_OK) {
|
||||
phost->host_state = HOST_CLASS_PROCESS;
|
||||
} else {
|
||||
usb_host_errorprocess(phost, tmp_status);
|
||||
}
|
||||
} else if (tmp_host_state == HOST_CLASS_PROCESS) {
|
||||
tmp_status = phost->class_callbk->host_class_process(pdev, phost);
|
||||
usb_host_errorprocess(phost, tmp_status);
|
||||
} else if (tmp_host_state == HOST_CTRL_TRANSMIT) {
|
||||
(void)usb_host_ctrlprocess(pdev, phost);
|
||||
} else if (tmp_host_state == HOST_ERROR_STATE) {
|
||||
usb_host_deinit(pdev, phost);
|
||||
phost->user_callbk->huser_deinit();
|
||||
phost->class_callbk->host_class_deinit(pdev);
|
||||
} else if (tmp_host_state == HOST_DEV_DISCONNECTED) {
|
||||
phost->user_callbk->huser_devdisconn();
|
||||
usb_host_deinit(pdev, phost);
|
||||
phost->user_callbk->huser_deinit();
|
||||
phost->class_callbk->host_class_deinit(pdev);
|
||||
usb_host_dedistrallch(pdev);
|
||||
phost->host_state = HOST_IDLE;
|
||||
|
||||
host_driver_init(pdev);
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief process the status when related error status happens.
|
||||
* @param [in] phost host state set
|
||||
* @param [in] errType host status
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_errorprocess(USBH_HOST *phost, HOST_STATUS errType)
|
||||
{
|
||||
switch (errType) {
|
||||
case HSTATUS_APP_DEINIT:
|
||||
phost->host_state = HOST_ERROR_STATE;
|
||||
phost->user_callbk->huser_init();
|
||||
break;
|
||||
case HSTATUS_SPEED_UNKNOWN:
|
||||
case HSTATUS_UNRECOVERED_ERROR:
|
||||
phost->user_callbk->huser_unrecoverederror();
|
||||
phost->host_state = HOST_ERROR_STATE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief this function process all the emunation steps.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_enumprocess(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
HOST_STATUS tmp_status;
|
||||
|
||||
ENUM_HANDLE_STATE tmp_enum_state;
|
||||
tmp_status = HSTATUS_BUSY;
|
||||
tmp_enum_state = phost->enum_state;
|
||||
if (tmp_enum_state == ENUM_IDLE) {
|
||||
if (usb_host_getdevdesc(pdev, phost, 8U) == HSTATUS_OK) {
|
||||
phost->ctrlparam.ctrlmaxsize = phost->device_prop.devdesc.bMaxPacketSize0;
|
||||
host_driver_portrst(pdev);
|
||||
phost->enum_state = ENUM_GET_FULL_DEVDESC;
|
||||
usb_host_mdfch(pdev,
|
||||
phost->ctrlparam.hc_num_out,
|
||||
0U,
|
||||
0U,
|
||||
0U,
|
||||
(uint16_t)phost->ctrlparam.ctrlmaxsize);
|
||||
usb_host_mdfch(pdev,
|
||||
phost->ctrlparam.hc_num_in,
|
||||
0U,
|
||||
0U,
|
||||
0U,
|
||||
(uint16_t)phost->ctrlparam.ctrlmaxsize);
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_FULL_DEVDESC) {
|
||||
if (usb_host_getdevdesc(pdev, phost, USB_DEVICE_DESC_SIZE) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_devdescavailable(&phost->device_prop.devdesc);
|
||||
phost->enum_state = ENUM_SET_DEVADDR;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_SET_DEVADDR) {
|
||||
if (usb_host_setdevaddr(pdev, phost, DEV_ASSIGNED_ADDRESS) == HSTATUS_OK) {
|
||||
usb_mdelay(2UL);
|
||||
phost->device_prop.devaddr = DEV_ASSIGNED_ADDRESS;
|
||||
phost->user_callbk->huser_devaddrdistributed();
|
||||
phost->enum_state = ENUM_GET_CFGDESC;
|
||||
usb_host_mdfch(pdev,
|
||||
phost->ctrlparam.hc_num_in,
|
||||
phost->device_prop.devaddr,
|
||||
0U,
|
||||
0U,
|
||||
0U);
|
||||
|
||||
usb_host_mdfch(pdev,
|
||||
phost->ctrlparam.hc_num_out,
|
||||
phost->device_prop.devaddr,
|
||||
0U,
|
||||
0U,
|
||||
0U);
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_CFGDESC) {
|
||||
if (usb_host_getcfgdesc(pdev, phost, USB_CONFIGURATION_DESC_SIZE) == HSTATUS_OK) {
|
||||
phost->enum_state = ENUM_GET_FULL_CFGDESC;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_FULL_CFGDESC) {
|
||||
if (usb_host_getcfgdesc(pdev, phost, phost->device_prop.devcfgdesc.wTotalLength) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_cfgdescavailable(&phost->device_prop.devcfgdesc,
|
||||
phost->device_prop.devitfdesc,
|
||||
phost->device_prop.devepdesc[0]);
|
||||
phost->enum_state = ENUM_GET_MFCSTRINGDESC;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_MFCSTRINGDESC) {
|
||||
if (phost->device_prop.devdesc.iManufacturer != (uint8_t)0) {
|
||||
if (usb_host_getstringdesc(pdev,
|
||||
phost,
|
||||
phost->device_prop.devdesc.iManufacturer,
|
||||
Local_Buffer,
|
||||
0xffu) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_mfcstring(Local_Buffer);
|
||||
phost->enum_state = ENUM_GET_PRODUCT_STRINGDESC;
|
||||
}
|
||||
} else {
|
||||
phost->user_callbk->huser_mfcstring("N/A");
|
||||
phost->enum_state = ENUM_GET_PRODUCT_STRINGDESC;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_PRODUCT_STRINGDESC) {
|
||||
if (phost->device_prop.devdesc.iProduct != (uint8_t)0) {
|
||||
if (usb_host_getstringdesc(pdev,
|
||||
phost,
|
||||
phost->device_prop.devdesc.iProduct,
|
||||
Local_Buffer,
|
||||
0xffu) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_productstring(Local_Buffer);
|
||||
phost->enum_state = ENUM_GET_SERIALNUM_STRINGDESC;
|
||||
}
|
||||
} else {
|
||||
phost->user_callbk->huser_productstring("N/A");
|
||||
phost->enum_state = ENUM_GET_SERIALNUM_STRINGDESC;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_GET_SERIALNUM_STRINGDESC) {
|
||||
if (phost->device_prop.devdesc.iSerialNumber != (uint8_t)0) {
|
||||
if (usb_host_getstringdesc(pdev,
|
||||
phost,
|
||||
phost->device_prop.devdesc.iSerialNumber,
|
||||
Local_Buffer,
|
||||
0xffu) == HSTATUS_OK) {
|
||||
phost->user_callbk->huser_serialnum(Local_Buffer);
|
||||
phost->enum_state = ENUM_SET_CFG;
|
||||
}
|
||||
} else {
|
||||
phost->user_callbk->huser_serialnum("N/A");
|
||||
phost->enum_state = ENUM_SET_CFG;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_SET_CFG) {
|
||||
if (usb_host_setconfig(pdev, phost,
|
||||
(uint16_t)phost->device_prop.devcfgdesc.bConfigurationValue) == HSTATUS_OK) {
|
||||
phost->enum_state = ENUM_DEV_CFG_OVER;
|
||||
}
|
||||
}
|
||||
if (tmp_enum_state == ENUM_DEV_CFG_OVER) {
|
||||
tmp_status = HSTATUS_OK;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
return tmp_status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief process the state machine of control transfer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_ctrlprocess(usb_core_instance *pdev, USBH_HOST *phost)
|
||||
{
|
||||
uint8_t direction;
|
||||
CTRL_HANDLE_STATE tmp_ctrl_state;
|
||||
static uint16_t timeout = 0;
|
||||
HOST_STATUS status = HSTATUS_OK;
|
||||
HOST_CH_XFER_STATE URB_Status;
|
||||
|
||||
phost->ctrlparam.ctrl_status = CTRL_START;
|
||||
tmp_ctrl_state = phost->ctrlparam.ctrl_state;
|
||||
|
||||
if (tmp_ctrl_state == CTRL_SETUP) {
|
||||
/* transmit a setup packet to the device */
|
||||
usb_host_sendctrlsetup(pdev, phost->ctrlparam.setup.d8, phost->ctrlparam.hc_num_out);
|
||||
phost->ctrlparam.ctrl_state = CTRL_SETUP_WAIT;
|
||||
timeout = DATA_STAGE_TIMEOUT * 6U;
|
||||
phost->ctrlparam.sof_num = (uint16_t)host_driver_getcurrentfrm(pdev);
|
||||
} else if (tmp_ctrl_state == CTRL_SETUP_WAIT) {
|
||||
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
|
||||
/* case SETUP packet sent successfully */
|
||||
if (URB_Status == HOST_CH_XFER_DONE) {
|
||||
/* parse the direction of the request from the setup just sent */
|
||||
direction = (phost->ctrlparam.setup.b.bmRequestType & USB_REQ_DIR_MASK);
|
||||
/* judge if there is a data stage, if wLength is not zero, there may be a in or out
|
||||
data stage */
|
||||
if (phost->ctrlparam.setup.b.wLength.w != 0U) {
|
||||
timeout = DATA_STAGE_TIMEOUT;
|
||||
if (direction == USB_D2H) {
|
||||
/* Data Direction is IN, device should send data in */
|
||||
phost->ctrlparam.ctrl_state = CTRL_DATA_IN;
|
||||
} else {
|
||||
/* Data Direction is OUT, host will send data out for device */
|
||||
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT;
|
||||
}
|
||||
}
|
||||
/* No DATA stage */
|
||||
else {
|
||||
timeout = NODATA_STAGE_TIMEOUT;
|
||||
/* If there is No Data Transfer Stage */
|
||||
if (direction == USB_D2H) {
|
||||
/* Data Direction is IN */
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
|
||||
} else {
|
||||
/* Data Direction is OUT */
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN;
|
||||
}
|
||||
}
|
||||
/* Set the delay timer to enable timeout for data stage completion */
|
||||
phost->ctrlparam.sof_num = (uint16_t)host_driver_getcurrentfrm(pdev);
|
||||
} else if (URB_Status == HOST_CH_XFER_ERROR) {
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
phost->ctrlparam.ctrl_status = CTRL_XACTERR;
|
||||
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
|
||||
#if (LL_PRINT_ENABLE == DDL_ON)
|
||||
DDL_Printf("Device not responding\r\n");
|
||||
#endif
|
||||
} else {
|
||||
;
|
||||
}
|
||||
} else if (tmp_ctrl_state == CTRL_DATA_IN) {
|
||||
/* Issue an IN token */
|
||||
usb_host_recvctrldata(pdev, phost->ctrlparam.buff, phost->ctrlparam.length, phost->ctrlparam.hc_num_in);
|
||||
phost->ctrlparam.ctrl_state = CTRL_DATA_IN_WAIT;
|
||||
} else if (tmp_ctrl_state == CTRL_DATA_IN_WAIT) {
|
||||
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_in);
|
||||
/* check is DATA packet transfered successfully */
|
||||
if (URB_Status == HOST_CH_XFER_DONE) {
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
|
||||
}
|
||||
/* manage error cases*/
|
||||
if (URB_Status == HOST_CH_XFER_STALL) {
|
||||
/* In stall case, return to previous machine state*/
|
||||
phost->host_state = phost->host_state_backup;
|
||||
} else if (URB_Status == HOST_CH_XFER_ERROR) {
|
||||
/* Device error */
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
|
||||
/* timeout for IN transfer */
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
} else if (tmp_ctrl_state == CTRL_DATA_OUT) {
|
||||
/* Start DATA out transfer (only one DATA packet)*/
|
||||
pdev->host.hc[phost->ctrlparam.hc_num_out].out_toggle = 1;
|
||||
|
||||
usb_host_sendctrldata(pdev,
|
||||
phost->ctrlparam.buff,
|
||||
phost->ctrlparam.length,
|
||||
phost->ctrlparam.hc_num_out);
|
||||
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT_WAIT;
|
||||
} else if (tmp_ctrl_state == CTRL_DATA_OUT_WAIT) {
|
||||
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
|
||||
switch (URB_Status) {
|
||||
case HOST_CH_XFER_DONE:
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN;
|
||||
break;
|
||||
case HOST_CH_XFER_STALL:
|
||||
phost->host_state = phost->host_state_backup;
|
||||
phost->ctrlparam.ctrl_state = CTRL_STALLED;
|
||||
break;
|
||||
case HOST_CH_XFER_UNREADY:
|
||||
phost->ctrlparam.ctrl_state = CTRL_DATA_OUT;
|
||||
break;
|
||||
case HOST_CH_XFER_ERROR:
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (tmp_ctrl_state == CTRL_STATUS_IN) {
|
||||
/* receive a packet with 0 byte */
|
||||
usb_host_recvctrldata(pdev, NULL, 0U, phost->ctrlparam.hc_num_in);
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_IN_WAIT;
|
||||
} else if (tmp_ctrl_state == CTRL_STATUS_IN_WAIT) {
|
||||
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_in);
|
||||
if (URB_Status == HOST_CH_XFER_DONE) {
|
||||
/* Control transfers completed, Exit the State Machine */
|
||||
phost->host_state = phost->host_state_backup;
|
||||
phost->ctrlparam.ctrl_state = CTRL_COMPLETE;
|
||||
} else if (URB_Status == HOST_CH_XFER_ERROR) {
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
} else if ((host_driver_getcurrentfrm(pdev) - phost->ctrlparam.sof_num) > timeout) {
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
} else if (URB_Status == HOST_CH_XFER_STALL) {
|
||||
/* Control transfers completed, Exit the State Machine */
|
||||
phost->host_state = phost->host_state_backup;
|
||||
phost->ctrlparam.ctrl_status = CTRL_STALL;
|
||||
status = HSTATUS_UNSUPPORTED;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
} else if (tmp_ctrl_state == CTRL_STATUS_OUT) {
|
||||
pdev->host.hc[phost->ctrlparam.hc_num_out].out_toggle ^= 1U;
|
||||
usb_host_sendctrldata(pdev, NULL, 0U, phost->ctrlparam.hc_num_out);
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT_WAIT;
|
||||
} else if (tmp_ctrl_state == CTRL_STATUS_OUT_WAIT) {
|
||||
URB_Status = host_driver_getxferstate(pdev, phost->ctrlparam.hc_num_out);
|
||||
switch (URB_Status) {
|
||||
case HOST_CH_XFER_DONE:
|
||||
phost->host_state = phost->host_state_backup;
|
||||
phost->ctrlparam.ctrl_state = CTRL_COMPLETE;
|
||||
break;
|
||||
case HOST_CH_XFER_UNREADY:
|
||||
phost->ctrlparam.ctrl_state = CTRL_STATUS_OUT;
|
||||
break;
|
||||
case HOST_CH_XFER_ERROR:
|
||||
phost->ctrlparam.ctrl_state = CTRL_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (tmp_ctrl_state == CTRL_ERROR) {
|
||||
if (++ phost->ctrlparam.err_cnt <= HOST_MAX_ERROR_CNT) {
|
||||
/* re-start the transmission, starting from SETUP packet */
|
||||
phost->ctrlparam.ctrl_state = CTRL_SETUP;
|
||||
} else {
|
||||
phost->ctrlparam.ctrl_status = CTRL_FAIL;
|
||||
phost->host_state = phost->host_state_backup;
|
||||
|
||||
status = HSTATUS_FAIL;
|
||||
}
|
||||
} else {
|
||||
;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_core.h
|
||||
* @brief header file for the usb_host_core.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_CORE_H__
|
||||
#define __USB_HOST_CORE_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
/* USBH_CORE_Exported_Defines */
|
||||
#define MSC_CLASS (0x08U)
|
||||
#define HID_CLASS (0x03U)
|
||||
#define MSC_PROTOCOL (0x50U)
|
||||
#define CBI_PROTOCOL (0x01U)
|
||||
|
||||
#define DEV_DEFAULT_ADDRESS (0U)
|
||||
#define DEV_ASSIGNED_ADDRESS (1U)
|
||||
|
||||
#define HOST_MAX_ERROR_CNT (2U)
|
||||
|
||||
#define ENUM_LOCAL_BUF (256U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void usb_host_init(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
usb_host_class_callback_func *class_cbk,
|
||||
usb_host_user_callback_func *user_cbk);
|
||||
extern void usb_host_deinit(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
extern void usb_host_mainprocess(usb_core_instance *pdev, USBH_HOST *phost);
|
||||
extern void usb_host_errorprocess(USBH_HOST *phost, HOST_STATUS errType);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_CORE_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_ctrltrans.c
|
||||
* @brief This file handles the issuing of the USB transactions
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_ctrltrans.h"
|
||||
#include "usb_host_driver.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
void usb_host_submitsetupreq(USBH_HOST *phost, uint8_t *buff, uint16_t length);
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief Start a setup transfer by changing the state-machine and
|
||||
* initializing the required variables needed for the Control Transfer
|
||||
* @param [in] phost host state set
|
||||
* @param [in] buff data buffer used for setup request
|
||||
* @param [in] length data length in byte
|
||||
* @retval status
|
||||
*/
|
||||
void usb_host_submitsetupreq(USBH_HOST *phost, uint8_t *buff, uint16_t length)
|
||||
{
|
||||
/* Save Global State */
|
||||
phost->host_state_backup = phost->host_state;
|
||||
/* Prepare the Transactions */
|
||||
phost->host_state = HOST_CTRL_TRANSMIT;
|
||||
phost->ctrlparam.buff = buff;
|
||||
phost->ctrlparam.length = length;
|
||||
phost->ctrlparam.ctrl_state = CTRL_SETUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send a control request and update the status after the request sent.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] buff data buffer whose data will be sent in the control pipe.
|
||||
* @param [in] length length of the data sent.
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_ctrlreq(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t *buff,
|
||||
uint16_t length)
|
||||
{
|
||||
HOST_STATUS status;
|
||||
REQ_HANDLE_STATE tmp_req_state;
|
||||
(void)(pdev);
|
||||
status = HSTATUS_BUSY;
|
||||
tmp_req_state = phost->req_state;
|
||||
if (tmp_req_state == REQ_CMD_TX) {
|
||||
/* prepare a setup packet for transferring */
|
||||
usb_host_submitsetupreq(phost, buff, length);
|
||||
/* update the request state */
|
||||
phost->req_state = REQ_CMD_WAIT;
|
||||
/* The status would be returned in this function */
|
||||
status = HSTATUS_BUSY;
|
||||
} else if (tmp_req_state == REQ_CMD_WAIT) {
|
||||
switch (phost->ctrlparam.ctrl_state) {
|
||||
case CTRL_COMPLETE:
|
||||
/* Commands have been successfully sent and Responses have been Received */
|
||||
phost->req_state = REQ_CMD_TX;
|
||||
/* update the control state */
|
||||
phost->ctrlparam.ctrl_state = CTRL_IDLE;
|
||||
status = HSTATUS_OK;
|
||||
break;
|
||||
case CTRL_ERROR:
|
||||
/* fail transfer */
|
||||
phost->req_state = REQ_CMD_TX;
|
||||
status = HSTATUS_FAIL;
|
||||
break;
|
||||
case CTRL_STALLED:
|
||||
/* Commands have been successfully sent and Responses have been Received */
|
||||
phost->req_state = REQ_CMD_TX;
|
||||
status = HSTATUS_UNSUPPORTED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends a setup packet to the control EP of the USB device
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer whose data will be sent in the control pipe to the control EP of the device.
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_sendctrlsetup(usb_core_instance *pdev, uint8_t *buff, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = 0U;
|
||||
pdev->host.hc[hc_num].pid_type = PID_SETUP;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = 8;
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends a data packet to the USB device
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer whose data will be sent to the USB device
|
||||
* @param [in] length the data length in byte that would be sent
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_sendctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = 0;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
if (length == 0U) {
|
||||
/* For Status OUT stage, Length==0, Status Out PID = 1 always */
|
||||
pdev->host.hc[hc_num].out_toggle = 1;
|
||||
}
|
||||
/* Set the Data Toggle bit */
|
||||
if (pdev->host.hc[hc_num].out_toggle == 0U) {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1 ;
|
||||
}
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives the response data to the setup packet
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer when received data.
|
||||
* @param [in] length the length data in byte have received.
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_recvctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sent the bulk packet to the device
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer whose data will be sent
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_sendbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = 0;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
/* Set the Data Toggle bit */
|
||||
if (pdev->host.hc[hc_num].out_toggle == 0U) {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1 ;
|
||||
}
|
||||
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief receives bulk packet from device
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff buffer to save the data received from the device
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval status
|
||||
*/
|
||||
void usb_host_recvbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
|
||||
|
||||
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1;
|
||||
}
|
||||
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief receives the device response to the Interrupt IN token
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff buffer to save the data received from the device
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_recvintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1;
|
||||
}
|
||||
/* toggle the DATA PID */
|
||||
pdev->host.hc[hc_num].in_toggle ^= (uint8_t)1;
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send the data on Interrupt OUT Endpoint
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer whose data will be sent
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_sentintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)0;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
|
||||
if (pdev->host.hc[hc_num].in_toggle == (uint8_t)0) {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA1;
|
||||
}
|
||||
|
||||
pdev->host.hc[hc_num].in_toggle ^= (uint8_t)1;
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief receives the Device Response to the Isochronous IN token
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff buffer to save the data received from the device
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_recvisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)1;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends the data through Isochronous OUT Endpoint
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] buff data buffer whose data will be sent
|
||||
* @param [in] length data length in byte
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_sendisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.hc[hc_num].is_epin = (uint8_t)0;
|
||||
pdev->host.hc[hc_num].xfer_buff = buff;
|
||||
pdev->host.hc[hc_num].xfer_len = length;
|
||||
pdev->host.hc[hc_num].pid_type = PID_DATA0;
|
||||
(void)host_driver_submitrequest(pdev, hc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_ctrltrans.h
|
||||
* @brief header file for the usb_host_ctrltrans.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_CTRLTRANS_H__
|
||||
#define __USB_HOST_CTRLTRANS_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void usb_host_sendctrlsetup(usb_core_instance *pdev, uint8_t *buff, uint8_t hc_num);
|
||||
extern void usb_host_sendctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern void usb_host_recvctrldata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern void usb_host_recvbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern void usb_host_sendbulkdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern void usb_host_recvintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern void usb_host_sentintdata(usb_core_instance *pdev, uint8_t *buff, uint16_t length, uint8_t hc_num);
|
||||
extern HOST_STATUS usb_host_ctrlreq(usb_core_instance *pdev, USBH_HOST *phost, uint8_t *buff, uint16_t length);
|
||||
extern void usb_host_recvisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num);
|
||||
extern void usb_host_sendisocdata(usb_core_instance *pdev, uint8_t *buff, uint32_t length, uint8_t hc_num);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_CTRLTRANS_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,430 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_def.h
|
||||
* @brief Definitions used in the USB host library
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_DEF_H__
|
||||
#define __USB_HOST_DEF_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "usb_app_conf.h"
|
||||
#include "usb_lib.h"
|
||||
#include "hc32_ll.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
/* This Union is copied from usb_core.h */
|
||||
typedef union {
|
||||
uint16_t w;
|
||||
struct BW {
|
||||
uint8_t msb;
|
||||
uint8_t lsb;
|
||||
}
|
||||
bw;
|
||||
} uint16_t_uint8_t;
|
||||
/* standard setup packet defination */
|
||||
typedef union {
|
||||
uint8_t d8[8];
|
||||
struct _SetupPkt_Struc {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t_uint8_t wValue;
|
||||
uint16_t_uint8_t wIndex;
|
||||
uint16_t_uint8_t wLength;
|
||||
} b;
|
||||
} usb_setup_typedef;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
} USB_HOST_DescHeader_TypeDef;
|
||||
|
||||
/* Standard Device Descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength; /* Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* Device descriptor type */
|
||||
uint16_t bcdUSB; /* USB Specification Release Numbrer in Binary-Coded Decimal(i.e.,2.10 is 210H) */
|
||||
uint8_t bDeviceClass; /* Class code(assigned by the USB-IF) */
|
||||
uint8_t bDeviceSubClass; /* Subclass code(assigned by the USB-IF) this code is qualified by the value of the \
|
||||
bDeviceClass field. */
|
||||
uint8_t bDeviceProtocol; /* Protocol code(assigned by the USB-IF), this code is qualified by the value of the \
|
||||
bDeviceClass and the bDeviceSubClass fields. */
|
||||
uint8_t bMaxPacketSize0; /* Maximum packet size for EP0 */
|
||||
uint16_t idVendor; /* Vendor ID (assigned by the USB-IF) */
|
||||
uint16_t idProduct; /* Product ID (assigned by manufacturer) */
|
||||
uint16_t bcdDevice; /* Device Release Number in binary-coded decimal */
|
||||
uint8_t iManufacturer; /* Index of string descriptor describing manufacturer */
|
||||
uint8_t iProduct; /* Index of string descriptor describing product */
|
||||
uint8_t iSerialNumber; /* Index of string descriptor describing the device's serial number */
|
||||
uint8_t bNumConfigurations; /* Number of possible configurations */
|
||||
} usb_host_devdesc_typedef;
|
||||
|
||||
/* Standard Configuration Descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength; /* Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* CONFIGURATION descriptor type */
|
||||
uint16_t wTotalLength; /* Total length of data returned for this configuration */
|
||||
uint8_t bNumInterfaces; /* Number of interfaces supported by this configuration */
|
||||
uint8_t bConfigurationValue; /* Value to use as an argument to the SetConfiguration() request to select this configuration */
|
||||
uint8_t iConfiguration; /* Index of string descriptor describing this configuration */
|
||||
uint8_t bmAttributes; /* Configuration characteristics: D7:Reserved(set to one) D6:Self-powered D5:Remote Wakeup D4..0 Reserved(set to zero) */
|
||||
uint8_t bMaxPower; /* Maximum power consumption of the device from the bus in this specific configuration when the device is fully operational */
|
||||
} usb_host_cfgdesc_typedef;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */
|
||||
uint8_t bCountryCode; /* specifies the transfer type. */
|
||||
uint8_t bNumDescriptors; /* specifies the transfer type. */
|
||||
uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */
|
||||
uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */
|
||||
} USB_HOST_HIDDesc_TypeDef;
|
||||
|
||||
/* Standard Interface Descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength; /* Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* INTERFACE Descriptor Type */
|
||||
uint8_t bInterfaceNumber; /* Number of this interface */
|
||||
uint8_t bAlternateSetting; /* Value used to select this alternate setting for the interface identifiled in the \
|
||||
prior field */
|
||||
uint8_t bNumEndpoints; /* Number of Endpoints used by this interface */
|
||||
uint8_t bInterfaceClass; /* Class code (assigned by the USB-IF) */
|
||||
uint8_t bInterfaceSubClass; /* Subclass code (assigned by the USB-IF) */
|
||||
uint8_t bInterfaceProtocol; /* Protocol code (assigned by the USB) */
|
||||
uint8_t iInterface; /* Index of string descriptor describing this interface */
|
||||
} usb_host_itfdesc_typedef;
|
||||
|
||||
/* Standard Endpoint Descriptor */
|
||||
typedef struct {
|
||||
uint8_t bLength; /* Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /* ENDPOINT descriptor type */
|
||||
uint8_t bEndpointAddress; /* The address of the endpoint on the device described by this descriptor */
|
||||
uint8_t bmAttributes; /* refer to the related standard of USB 2.0 */
|
||||
uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving when this \
|
||||
configuration is selected */
|
||||
uint8_t bInterval; /* Interval for servicing the endpoint for data transfers */
|
||||
} USB_HOST_EPDesc_TypeDef;
|
||||
|
||||
/* USBH_CORE_Exported_Types */
|
||||
/* Host status */
|
||||
typedef enum {
|
||||
HSTATUS_OK = 0,
|
||||
HSTATUS_BUSY,
|
||||
HSTATUS_FAIL,
|
||||
HSTATUS_UNSUPPORTED,
|
||||
HSTATUS_UNRECOVERED_ERROR,
|
||||
HSTATUS_SPEED_UNKNOWN,
|
||||
HSTATUS_APP_DEINIT
|
||||
} HOST_STATUS;
|
||||
|
||||
/* states about the handle stages on the host side */
|
||||
typedef enum {
|
||||
HOST_IDLE = 0,
|
||||
HOST_DEV_CONNECTED,
|
||||
HOST_DEV_DISCONNECTED,
|
||||
HOST_GET_DEVSPEED,
|
||||
HOST_ENUM,
|
||||
HOST_CLASS_REQ,
|
||||
HOST_CLASS_PROCESS,
|
||||
HOST_CTRL_TRANSMIT,
|
||||
HOST_USER_INPUT,
|
||||
HOST_SUSPENDED,
|
||||
HOST_ERROR_STATE
|
||||
} HOST_HANDLE_STATE;
|
||||
|
||||
|
||||
/* states of the enumeration stage on the host side */
|
||||
typedef enum {
|
||||
ENUM_IDLE = 0,
|
||||
ENUM_GET_FULL_DEVDESC,
|
||||
ENUM_SET_DEVADDR,
|
||||
ENUM_GET_CFGDESC,
|
||||
ENUM_GET_FULL_CFGDESC,
|
||||
ENUM_GET_MFCSTRINGDESC,
|
||||
ENUM_GET_PRODUCT_STRINGDESC,
|
||||
ENUM_GET_SERIALNUM_STRINGDESC,
|
||||
ENUM_SET_CFG,
|
||||
ENUM_DEV_CFG_OVER
|
||||
} ENUM_HANDLE_STATE;
|
||||
|
||||
/* states of the control stages on the host side */
|
||||
typedef enum {
|
||||
CTRL_IDLE = 0,
|
||||
CTRL_SETUP,
|
||||
CTRL_SETUP_WAIT,
|
||||
CTRL_DATA_IN,
|
||||
CTRL_DATA_IN_WAIT,
|
||||
CTRL_DATA_OUT,
|
||||
CTRL_DATA_OUT_WAIT,
|
||||
CTRL_STATUS_IN,
|
||||
CTRL_STATUS_IN_WAIT,
|
||||
CTRL_STATUS_OUT,
|
||||
CTRL_STATUS_OUT_WAIT,
|
||||
CTRL_ERROR,
|
||||
CTRL_STALLED,
|
||||
CTRL_COMPLETE
|
||||
} CTRL_HANDLE_STATE;
|
||||
|
||||
/* Following states are state machine for the request transferring */
|
||||
typedef enum {
|
||||
REQ_CMD_IDLE = 0,
|
||||
REQ_CMD_TX,
|
||||
REQ_CMD_WAIT
|
||||
} REQ_HANDLE_STATE;
|
||||
|
||||
typedef enum {
|
||||
USER_HAVE_RESP = 0,
|
||||
USER_NONE_RESP
|
||||
} HOST_USER_STATUS;
|
||||
|
||||
typedef struct {
|
||||
uint8_t hc_num_in; /* channel number for the IN EP */
|
||||
uint8_t hc_num_out; /* channel number for the OUT EP */
|
||||
uint8_t ctrlmaxsize; /* the max size of EP0 parsed from the device descriptor */
|
||||
uint8_t err_cnt; /* the error counter */
|
||||
uint16_t sof_num; /* the frame number for sof packet */
|
||||
uint16_t length; /* length of data in byte */
|
||||
uint8_t *buff; /* data buffer */
|
||||
CTRL_HANDLE_STATUS ctrl_status; /* status of control pipe */
|
||||
CTRL_HANDLE_STATE ctrl_state; /* running state of the control transfer */
|
||||
usb_setup_typedef setup; /* setup packet */
|
||||
} usb_host_ctrl_param;
|
||||
|
||||
/* Device information parsed from the related descriptors requested from the connected device
|
||||
the following data are all parsed from the data sent by the connnected device */
|
||||
typedef struct {
|
||||
uint8_t devaddr; /* the address of the connected device */
|
||||
uint8_t devspeed; /* the core speed of the connected device */
|
||||
usb_host_devdesc_typedef devdesc; /* the device descriptor parsed from the data sent by device */
|
||||
usb_host_cfgdesc_typedef devcfgdesc; /* the device configuration descriptor parsed from the data sent by device */
|
||||
usb_host_itfdesc_typedef devitfdesc[USBH_MAX_NUM_INTERFACES]; /* the interface descritpor */
|
||||
USB_HOST_EPDesc_TypeDef devepdesc[USBH_MAX_NUM_INTERFACES][USBH_MAX_NUM_ENDPOINTS]; /* the endpoint descriptor */
|
||||
USB_HOST_HIDDesc_TypeDef hiddesc; /* the hid descriptor */
|
||||
} usb_host_devinformation;
|
||||
|
||||
typedef struct {
|
||||
HOST_STATUS(*host_class_init)(usb_core_instance *pdev, void *phost);
|
||||
void (*host_class_deinit)(usb_core_instance *pdev);
|
||||
HOST_STATUS(*host_class_request)(usb_core_instance *pdev, void *phost);
|
||||
HOST_STATUS(*host_class_process)(usb_core_instance *pdev, void *phost);
|
||||
} usb_host_class_callback_func;
|
||||
|
||||
typedef struct {
|
||||
void (*huser_init)(void);
|
||||
void (*huser_deinit)(void);
|
||||
void (*huser_devattached)(void);
|
||||
void (*huser_devreset)(void);
|
||||
void (*huser_devdisconn)(void);
|
||||
void (*huser_overcurrent)(void);
|
||||
void (*huser_devspddetected)(uint8_t DeviceSpeed);
|
||||
void (*huser_devdescavailable)(void *);
|
||||
void (*huser_devaddrdistributed)(void);
|
||||
void (*huser_cfgdescavailable)(usb_host_cfgdesc_typedef *,
|
||||
usb_host_itfdesc_typedef *,
|
||||
USB_HOST_EPDesc_TypeDef *);
|
||||
/* Configuration Descriptor available */
|
||||
void (*huser_mfcstring)(void *);
|
||||
void (*huser_productstring)(void *);
|
||||
void (*huser_serialnum)(void *);
|
||||
void (*huser_enumcompl)(void);
|
||||
HOST_USER_STATUS(*huser_userinput)(void);
|
||||
int (*huser_application)(void);
|
||||
void (*huser_devunsupported)(void);
|
||||
void (*huser_unrecoverederror)(void);
|
||||
} usb_host_user_callback_func;
|
||||
|
||||
typedef struct {
|
||||
/* states for the host, enumeration, request */
|
||||
REQ_HANDLE_STATE req_state; /* value of state machine about the request */
|
||||
ENUM_HANDLE_STATE enum_state; /* state machine while enumerating */
|
||||
HOST_HANDLE_STATE host_state_backup; /* backup value of state machine about the host */
|
||||
HOST_HANDLE_STATE host_state; /* value of state machine about the host */
|
||||
/* control informations */
|
||||
usb_host_ctrl_param ctrlparam; /* values about the control parameters */
|
||||
/* device information parsed from the descriptors from the device */
|
||||
usb_host_devinformation device_prop;
|
||||
/* functions: call back functions for the class and user */
|
||||
usb_host_class_callback_func *class_callbk;
|
||||
usb_host_user_callback_func *user_callbk;
|
||||
} USBH_HOST;
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0U
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1U
|
||||
#endif
|
||||
|
||||
/* Get a 16bits data from buffer in little end mode. */
|
||||
#define SMALL_END(addr) (((uint16_t)(*((uint8_t *)(addr)))) + (((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U))
|
||||
|
||||
#define USB_LEN_CFG_DESC (0x09U)
|
||||
|
||||
/* bmRequestType
|
||||
D7: Data transfer direction
|
||||
0 = Host-to-device
|
||||
1 = Device-to-host
|
||||
*/
|
||||
#define USB_REQ_DIR_MASK (0x80U)
|
||||
#define USB_H2D (0x00U)
|
||||
#define USB_D2H (0x80U)
|
||||
|
||||
/* bmRequestType
|
||||
D6...5: Type
|
||||
0 = Standard
|
||||
1 = Class
|
||||
2 = Vendor
|
||||
3 = Reserved
|
||||
*/
|
||||
#define USB_REQ_TYPE_STANDARD (0x00U)
|
||||
#define USB_REQ_TYPE_CLASS (0x20U)
|
||||
#define USB_REQ_TYPE_VENDOR (0x40U)
|
||||
#define USB_REQ_TYPE_RESERVED (0x60U)
|
||||
|
||||
/* bmRequestType
|
||||
D4...0: Recipient
|
||||
0 = Device
|
||||
1 = Interface
|
||||
2 = Endpoint
|
||||
3 = Other
|
||||
4...31 = Reserved
|
||||
*/
|
||||
#define USB_REQ_RECIPIENT_DEVICE (0x00U)
|
||||
#define USB_REQ_RECIPIENT_INTERFACE (0x01U)
|
||||
#define USB_REQ_RECIPIENT_ENDPOINT (0x02U)
|
||||
#define USB_REQ_RECIPIENT_OTHER (0x03U)
|
||||
|
||||
/* Table 9-4. Standard Request Codes [USB Specification] */
|
||||
/* bRequest Value */
|
||||
#define USB_REQ_GET_STATUS (0x00U)
|
||||
#define USB_REQ_CLEAR_FEATURE (0x01U)
|
||||
#define USB_REQ_SET_FEATURE (0x03U)
|
||||
#define USB_REQ_SET_ADDRESS (0x05U)
|
||||
#define USB_REQ_GET_DESCRIPTOR (0x06U)
|
||||
#define USB_REQ_SET_DESCRIPTOR (0x07U)
|
||||
#define USB_REQ_GET_CONFIGURATION (0x08U)
|
||||
#define USB_REQ_SET_CONFIGURATION (0x09U)
|
||||
#define USB_REQ_GET_INTERFACE (0x0AU)
|
||||
#define USB_REQ_SET_INTERFACE (0x0BU)
|
||||
#define USB_REQ_SYNCH_FRAME (0x0Cu)
|
||||
|
||||
/* Table 9-5. Descriptor Types [USB Specification] */
|
||||
/* Descriptor Types Value */
|
||||
#define USB_DESC_TYPE_DEVICE (1U)
|
||||
#define USB_DESC_TYPE_CONFIGURATION (2U)
|
||||
#define USB_DESC_TYPE_STRING (3U)
|
||||
#define USB_DESC_TYPE_INTERFACE (4U)
|
||||
#define USB_DESC_TYPE_ENDPOINT (5U)
|
||||
#define USB_DESC_TYPE_DEVICE_QUALIFIER (6U)
|
||||
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION (7U)
|
||||
#define USB_DESC_TYPE_INTERFACE_POWER (8U)
|
||||
#define USB_DESC_TYPE_HID (0x21U)
|
||||
#define USB_DESC_TYPE_HID_REPORT (0x22U)
|
||||
|
||||
#define USB_DEVICE_DESC_SIZE (18U)
|
||||
#define USB_CONFIGURATION_DESC_SIZE (9U)
|
||||
#define USB_HID_DESC_SIZE (9U)
|
||||
#define USB_INTERFACE_DESC_SIZE (9U)
|
||||
#define USB_ENDPOINT_DESC_SIZE (7U)
|
||||
|
||||
/* Descriptor Type and Descriptor Index */
|
||||
/* Use the following values when calling the function usb_host_getdesc */
|
||||
#define USB_DESC_DEVICE (((uint16_t)USB_DESC_TYPE_DEVICE << 8U) & 0xFF00U)
|
||||
#define USB_DESC_CONFIGURATION (((uint16_t)USB_DESC_TYPE_CONFIGURATION << 8U) & 0xFF00U)
|
||||
#define USB_DESC_STRING (((uint16_t)USB_DESC_TYPE_STRING << 8U) & 0xFF00U)
|
||||
#define USB_DESC_INTERFACE (((uint16_t)USB_DESC_TYPE_INTERFACE << 8U) & 0xFF00U)
|
||||
#define USB_DESC_ENDPOINT (((uint16_t)USB_DESC_TYPE_INTERFACE << 8U) & 0xFF00U)
|
||||
#define USB_DESC_DEVICE_QUALIFIER (((uint16_t)USB_DESC_TYPE_DEVICE_QUALIFIER << 8U) & 0xFF00U)
|
||||
#define USB_DESC_OTHER_SPEED_CONFIGURATION (((uint16_t)USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8U) & 0xFF00U)
|
||||
#define USB_DESC_INTERFACE_POWER (((uint16_t)USB_DESC_TYPE_INTERFACE_POWER << 8U) & 0xFF00U)
|
||||
#define USB_DESC_HID_REPORT (((uint16_t)USB_DESC_TYPE_HID_REPORT << 8U) & 0xFF00U)
|
||||
#define USB_DESC_HID (((uint16_t)USB_DESC_TYPE_HID << 8U) & 0xFF00U)
|
||||
|
||||
#define USB_EP_DIR_OUT (0x00U)
|
||||
#define USB_EP_DIR_IN (0x80U)
|
||||
#define USB_EP_DIR_MSK (0x80U)
|
||||
|
||||
/* supported classes */
|
||||
#define USB_MSC_CLASS (0x08U)
|
||||
#define USB_HID_CLASS (0x03U)
|
||||
|
||||
/* Interface Descriptor field values for HID Boot Protocol */
|
||||
#define HID_BOOT_CODE (0x01U)
|
||||
#define HID_KEYBRD_BOOT_CODE (0x01U)
|
||||
#define HID_MOUSE_BOOT_CODE (0x02U)
|
||||
|
||||
/* As per USB specs 9.2.6.4 :Standard request with data request timeout: 5sec
|
||||
Standard request with no data stage timeout : 50ms */
|
||||
#define DATA_STAGE_TIMEOUT (5000U)
|
||||
#define NODATA_STAGE_TIMEOUT (50U)
|
||||
|
||||
/* Macro definations for host mode */
|
||||
#define PID_DATA0 (0U)
|
||||
#define PID_DATA2 (1U)
|
||||
#define PID_DATA1 (2U)
|
||||
#define PID_SETUP (3U)
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_DEF_H__ */
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_driver.c
|
||||
* @brief Host Interface Layer.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_driver.h"
|
||||
#include "usb_bsp.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief Initialize the driver for the host mode
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void host_driver_init(usb_core_instance *pdev)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
pdev->host.is_dev_connect = 0U;
|
||||
for (i = 0U; i < USB_MAX_TX_FIFOS; i++) {
|
||||
pdev->host.ErrCnt[i] = 0U;
|
||||
pdev->host.XferCnt[i] = 0U;
|
||||
pdev->host.HC_Status[i] = HOST_CH_IDLE;
|
||||
}
|
||||
pdev->host.hc[0].max_packet = 8U;
|
||||
|
||||
usb_setregaddr(&pdev->regs, &pdev->basic_cfgs);;
|
||||
|
||||
usb_gintdis(&pdev->regs);
|
||||
usb_initusbcore(&pdev->regs, &pdev->basic_cfgs);
|
||||
/* force to work in host mode*/
|
||||
usb_modeset(&pdev->regs, HOST_MODE);
|
||||
/* configure charge pump IO */
|
||||
usb_bsp_cfgvbus(&pdev->regs);
|
||||
usb_vbusctrl(&pdev->regs, 1U);
|
||||
usb_mdelay(50UL);
|
||||
|
||||
usb_hostmodeinit(&pdev->regs, &pdev->basic_cfgs);
|
||||
usb_ginten(&pdev->regs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get current speed when in host mode
|
||||
* @param [in] pdev device instance
|
||||
* @retval current speed
|
||||
*/
|
||||
uint32_t host_driver_getcurrentspd(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hppt;
|
||||
u32hppt = READ_REG32(*pdev->regs.HPRT);
|
||||
return ((u32hppt & USBFS_HPRT_PSPD) >> USBFS_HPRT_PSPD_POS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get current DM DP state
|
||||
* @param [in] pdev device instance
|
||||
* @retval DM DP state
|
||||
* 0x00 DM L, DP L
|
||||
* 0x01 DM L, DP H
|
||||
* 0x02 DM H, DP L
|
||||
* 0x03 DM H, DP H
|
||||
*/
|
||||
uint32_t host_driver_getdmdpstate(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hppt;
|
||||
u32hppt = READ_REG32(*pdev->regs.HPRT);
|
||||
return ((u32hppt & USBFS_HPRT_PLSTS) >> USBFS_HPRT_PLSTS_POS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get vbus drive state
|
||||
* @param [in] pdev device instance
|
||||
* @retval vbus driver state
|
||||
* 0x00 vbus driver disable
|
||||
* 0x01 vbus driver enable
|
||||
*/
|
||||
uint32_t host_driver_getvbusdrivestate(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hppt;
|
||||
u32hppt = READ_REG32(*pdev->regs.HPRT);
|
||||
return ((u32hppt & USBFS_HPRT_PWPR) >> USBFS_HPRT_PWPR_POS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reset the port
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void host_driver_portrst(usb_core_instance *pdev)
|
||||
{
|
||||
usb_hprtrst(&pdev->regs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the connected status of the device
|
||||
* @param [in] pdev device instance
|
||||
* @retval 1 connected or 0 disconnected
|
||||
*/
|
||||
uint32_t host_driver_ifdevconnected(usb_core_instance *pdev)
|
||||
{
|
||||
return (pdev->host.is_dev_connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gets the frame number for of sof packet
|
||||
* @param [in] pdev device instance
|
||||
* @retval number of frame
|
||||
*/
|
||||
uint32_t host_driver_getcurrentfrm(usb_core_instance *pdev)
|
||||
{
|
||||
return (READ_REG32(pdev->regs.HREGS->HFNUM) & 0xFFFFUL) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gets the last xfer state
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel number
|
||||
* @retval HOST_CH_XFER_STATE
|
||||
*/
|
||||
HOST_CH_XFER_STATE host_driver_getxferstate(usb_core_instance *pdev, uint8_t ch_num)
|
||||
{
|
||||
return pdev->host.URB_State[ch_num] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gets the xfer count
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel number
|
||||
* @retval number of data trandmitted in bytes
|
||||
*/
|
||||
uint32_t host_driver_getxfercnt(usb_core_instance *pdev, uint8_t ch_num)
|
||||
{
|
||||
return pdev->host.XferCnt[ch_num] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gets the host channel status
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel number
|
||||
* @retval HOST_CH_STATUS
|
||||
*/
|
||||
HOST_CH_STATUS host_driver_gethostchstate(usb_core_instance *pdev, uint8_t ch_num)
|
||||
{
|
||||
return pdev->host.HC_Status[ch_num] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prepare a host channel and start a transfer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] hc_num channel number
|
||||
* @retval status
|
||||
*/
|
||||
uint32_t host_driver_hostch_init(usb_core_instance *pdev, uint8_t hc_num)
|
||||
{
|
||||
return usb_inithch(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief prepare a host channel and start a transfer
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] hc_num channel number
|
||||
* @retval status
|
||||
*/
|
||||
uint32_t host_driver_submitrequest(usb_core_instance *pdev, uint8_t hc_num)
|
||||
{
|
||||
pdev->host.URB_State[hc_num] = HOST_CH_XFER_IDLE;
|
||||
pdev->host.hc[hc_num].xfer_count = 0U ;
|
||||
return usb_hchtransbegin(&pdev->regs, hc_num, &pdev->host.hc[hc_num], pdev->basic_cfgs.dmaen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_driver.h
|
||||
* @brief Head file for usb_host_driver.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_DRIVER_H__
|
||||
#define __USB_HOST_DRIVER_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void host_driver_init(usb_core_instance *pdev);
|
||||
extern uint32_t host_driver_hostch_init(usb_core_instance *pdev, uint8_t hc_num);
|
||||
extern uint32_t host_driver_submitrequest(usb_core_instance *pdev, uint8_t hc_num);
|
||||
extern uint32_t host_driver_getcurrentspd(usb_core_instance *pdev);
|
||||
extern uint32_t host_driver_getdmdpstate(usb_core_instance *pdev);
|
||||
extern uint32_t host_driver_getvbusdrivestate(usb_core_instance *pdev);
|
||||
extern void host_driver_portrst(usb_core_instance *pdev);
|
||||
extern uint32_t host_driver_ifdevconnected(usb_core_instance *pdev);
|
||||
extern uint32_t host_driver_getcurrentfrm(usb_core_instance *pdev);
|
||||
extern HOST_CH_XFER_STATE host_driver_getxferstate(usb_core_instance *pdev, uint8_t ch_num);
|
||||
extern uint32_t host_driver_getxfercnt(usb_core_instance *pdev, uint8_t ch_num);
|
||||
extern HOST_CH_STATUS host_driver_gethostchstate(usb_core_instance *pdev, uint8_t ch_num);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_DRIVER_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_int.c
|
||||
* @brief Host driver interrupt subroutines.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_int.h"
|
||||
#include "usb_host_driver.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
void usb_host_hc_isr(usb_core_instance *pdev);
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief processes interrupt for a specific host channel which is used for OUT EP
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] chnum channel index
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_chx_out_isr(usb_core_instance *pdev, uint8_t chnum)
|
||||
{
|
||||
uint32_t u32hcchar;
|
||||
uint32_t u32hcint;
|
||||
uint32_t u32hcintmsk;
|
||||
|
||||
u32hcchar = READ_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR);
|
||||
u32hcint = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINT);
|
||||
u32hcintmsk = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINTMSK);
|
||||
u32hcint = u32hcint & u32hcintmsk;
|
||||
|
||||
if (0UL != (u32hcint & USBFS_HCINT_ACK)) {
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_ACK);
|
||||
}
|
||||
#if defined (HC32F4A0)
|
||||
else if (0UL != (u32hcint & USBFS_HCINT_AHBERR)) {
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_AHBERR);
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
}
|
||||
#endif
|
||||
else if (0UL != (u32hcint & USBFS_HCINT_FRMOR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_FRMOR);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_XFRC)) {
|
||||
pdev->host.ErrCnt[chnum] = 0U;
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_XFRC);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_XFERCOMPL;
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_STALL)) {
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_STALL);
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_STALL;
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_NAK)) {
|
||||
pdev->host.ErrCnt[chnum] = 0U;
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_NAK;
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_TXERR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
pdev->host.ErrCnt[chnum] ++;
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_XACTERR;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_TXERR);
|
||||
} else if (0UL != (u32hcint & HCINT_NYET)) {
|
||||
pdev->host.ErrCnt[chnum] = 0U;
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, HCINT_NYET);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_NYET;
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_DTERR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_DATATGLERR;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_DTERR);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_CHH)) {
|
||||
usb_host_int_mskchhltd(pdev, chnum);
|
||||
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
|
||||
|
||||
if (((u32hcchar & USBFS_HCCHAR_EPTYP) >> USBFS_HCCHAR_EPTYP_POS) == EP_TYPE_BULK) {
|
||||
pdev->host.hc[chnum].out_toggle ^= 1U;
|
||||
}
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_NAK) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_UNREADY;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_NYET) {
|
||||
if (pdev->host.hc[chnum].do_ping == 1U) {
|
||||
usb_pingtokenissue(&pdev->regs, chnum);
|
||||
}
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_UNREADY;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_STALL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_STALL;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_XACTERR) {
|
||||
if (pdev->host.ErrCnt[chnum] == 3UL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
|
||||
pdev->host.ErrCnt[chnum] = 0UL;
|
||||
}
|
||||
} else {
|
||||
;
|
||||
}
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_CHH);
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief processes interrupt for a specific host Channel which is used for IN EP
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] chnum channel index
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_chx_in_isr(usb_core_instance *pdev, uint8_t chnum)
|
||||
{
|
||||
uint32_t u32hcchar;
|
||||
uint32_t u32hctsiz;
|
||||
uint32_t u32eptypetmp;
|
||||
uint32_t u32hcint;
|
||||
uint32_t u32hcintmsk;
|
||||
|
||||
u32hcchar = READ_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR);
|
||||
u32hcint = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINT);
|
||||
u32hcintmsk = READ_REG32(pdev->regs.HC_REGS[chnum]->HCINTMSK);
|
||||
u32hcint = u32hcint & u32hcintmsk;
|
||||
|
||||
u32eptypetmp = (u32hcchar & USBFS_HCCHAR_EPTYP) >> USBFS_HCCHAR_EPTYP_POS;
|
||||
if (0UL != (u32hcint & USBFS_HCINT_ACK)) {
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_ACK);
|
||||
}
|
||||
#if defined (HC32F4A0)
|
||||
else if (0UL != (u32hcint & USBFS_HCINT_AHBERR)) {
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_AHBERR);
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
}
|
||||
#endif
|
||||
else if (0UL != (u32hcint & USBFS_HCINT_STALL)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_STALL;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_STALL);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_DTERR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_DATATGLERR;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_DTERR);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_FRMOR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_FRMOR);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_XFRC)) {
|
||||
if (pdev->basic_cfgs.dmaen == 1U) {
|
||||
u32hctsiz = READ_REG32(pdev->regs.HC_REGS[chnum]->HCTSIZ);
|
||||
pdev->host.XferCnt[chnum] = pdev->host.hc[chnum].xfer_len - (u32hctsiz & USBFS_HCTSIZ_XFRSIZ);
|
||||
}
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_XFERCOMPL;
|
||||
pdev->host.ErrCnt [chnum] = 0U;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_XFRC);
|
||||
switch (u32eptypetmp) {
|
||||
case EP_TYPE_CTRL:
|
||||
case EP_TYPE_BULK:
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
pdev->host.hc[chnum].in_toggle ^= (uint8_t)1;
|
||||
break;
|
||||
case EP_TYPE_INTR:
|
||||
u32hcchar |= USBFS_HCCHAR_ODDFRM;
|
||||
WRITE_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR, u32hcchar);
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
|
||||
break;
|
||||
case EP_TYPE_ISOC:
|
||||
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_CHH)) {
|
||||
usb_host_int_mskchhltd(pdev, chnum);
|
||||
if (pdev->host.HC_Status[chnum] == HOST_CH_XFERCOMPL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_DONE;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_STALL) {
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_STALL;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_XACTERR) {
|
||||
pdev->host.ErrCnt[chnum] = 0U;
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
|
||||
} else if (pdev->host.HC_Status[chnum] == HOST_CH_DATATGLERR) {
|
||||
pdev->host.ErrCnt[chnum] = 0U;
|
||||
pdev->host.URB_State[chnum] = HOST_CH_XFER_ERROR;
|
||||
} else if (u32eptypetmp == EP_TYPE_INTR) {
|
||||
pdev->host.hc[chnum].in_toggle ^= (uint8_t)1;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_CHH);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_TXERR)) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
pdev->host.ErrCnt[chnum] ++;
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_XACTERR;
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_TXERR);
|
||||
} else if (0UL != (u32hcint & USBFS_HCINT_NAK)) {
|
||||
if (u32eptypetmp == EP_TYPE_INTR) {
|
||||
usb_host_int_unmskchhltd(pdev, chnum);
|
||||
usb_hchstop(&pdev->regs, chnum);
|
||||
} else if ((u32eptypetmp == EP_TYPE_CTRL) || (u32eptypetmp == EP_TYPE_BULK)) {
|
||||
u32hcchar |= USBFS_HCCHAR_CHENA;
|
||||
u32hcchar &= ~USBFS_HCCHAR_CHDIS;
|
||||
WRITE_REG32(pdev->regs.HC_REGS[chnum]->HCCHAR, u32hcchar);
|
||||
} else {
|
||||
;
|
||||
}
|
||||
pdev->host.HC_Status[chnum] = HOST_CH_NAK;
|
||||
usb_host_clrint(pdev, chnum, USBFS_HCINT_NAK);
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief this function processes the channel interrupt
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_hc_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hcchar;
|
||||
uint8_t u8Cnt;
|
||||
uint32_t u32haint;
|
||||
|
||||
u32haint = READ_REG32(pdev->regs.HREGS->HAINT);
|
||||
for (u8Cnt = 0U; u8Cnt < pdev->basic_cfgs.host_chnum; u8Cnt++) {
|
||||
if (0UL != (u32haint & (1UL << u8Cnt))) {
|
||||
u32hcchar = READ_REG32(pdev->regs.HC_REGS[u8Cnt]->HCCHAR);
|
||||
if (0UL != ((u32hcchar & USBFS_HCCHAR_EPDIR) >> USBFS_HCCHAR_EPDIR_POS)) {
|
||||
usb_host_chx_in_isr(pdev, u8Cnt);
|
||||
} else {
|
||||
usb_host_chx_out_isr(pdev, u8Cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief process the start-of-frame interrupt in host mode.
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_sof_isr(usb_core_instance *pdev)
|
||||
{
|
||||
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_SOF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief processes disconnect interrupt
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_disconn_isr(usb_core_instance *pdev)
|
||||
{
|
||||
usb_gintdis(&pdev->regs);
|
||||
usb_vbusctrl(&pdev->regs, 0U);
|
||||
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_DISCINT);
|
||||
|
||||
pdev->host.is_dev_connect = 0U;
|
||||
}
|
||||
|
||||
#define USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM_POS (27U)
|
||||
#define USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM (0x78000000UL)
|
||||
/**
|
||||
* @brief processes non-periodic txFIFO empty interrupt.
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_nptxfifoempty_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hnptxsts;
|
||||
uint16_t u16LenWord;
|
||||
uint16_t u16Len;
|
||||
uint8_t u8ChNum;
|
||||
|
||||
u32hnptxsts = READ_REG32(pdev->regs.GREGS->HNPTXSTS);
|
||||
u8ChNum = (uint8_t)((u32hnptxsts & USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM) >> USBFS_HNPTXSTS_NPTXQTOP_CHEPNUM_POS);
|
||||
|
||||
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
|
||||
while (((u32hnptxsts & USBFS_HNPTXSTS_NPTXFSAV) > u16LenWord) && (pdev->host.hc[u8ChNum].xfer_len != 0U)) {
|
||||
u16Len = (uint16_t)((u32hnptxsts & USBFS_HNPTXSTS_NPTXFSAV) * 4UL);
|
||||
if (u16Len > pdev->host.hc[u8ChNum].xfer_len) {
|
||||
u16Len = (uint16_t)pdev->host.hc[u8ChNum].xfer_len;
|
||||
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_NPTXFE);
|
||||
}
|
||||
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
|
||||
usb_wrpkt(&pdev->regs, pdev->host.hc[u8ChNum].xfer_buff, u8ChNum, u16Len, pdev->basic_cfgs.dmaen);
|
||||
pdev->host.hc[u8ChNum].xfer_buff += u16Len;
|
||||
pdev->host.hc[u8ChNum].xfer_len -= u16Len;
|
||||
pdev->host.hc[u8ChNum].xfer_count += u16Len;
|
||||
u32hnptxsts = READ_REG32(pdev->regs.GREGS->HNPTXSTS);
|
||||
}
|
||||
}
|
||||
#define USBFS_HPTXSTS_PTXQTOP_CHNUM_POS (27U)
|
||||
#define USBFS_HPTXSTS_PTXQTOP_CHNUM (0x78000000UL)
|
||||
/**
|
||||
* @brief processes periodic txFIFO empty interrupt
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_ptxfifoempty_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hptxsts;
|
||||
uint16_t u16LenWord;
|
||||
uint16_t u16Len;
|
||||
uint8_t u8ChNum;
|
||||
|
||||
u32hptxsts = READ_REG32(pdev->regs.HREGS->HPTXSTS);
|
||||
u8ChNum = (uint8_t)((u32hptxsts & USBFS_HPTXSTS_PTXQTOP_CHNUM) >> USBFS_HPTXSTS_PTXQTOP_CHNUM_POS);
|
||||
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
|
||||
while ((((u32hptxsts & USBFS_HPTXSTS_PTXFSAVL)) > u16LenWord) && (pdev->host.hc[u8ChNum].xfer_len != 0U)) {
|
||||
u16Len = (uint16_t)((u32hptxsts & USBFS_HPTXSTS_PTXFSAVL) * 4UL);
|
||||
if (u16Len > pdev->host.hc[u8ChNum].xfer_len) {
|
||||
u16Len = (uint16_t)pdev->host.hc[u8ChNum].xfer_len;
|
||||
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTMSK_PTXFEM);
|
||||
}
|
||||
u16LenWord = (uint16_t)((pdev->host.hc[u8ChNum].xfer_len + 3UL) / 4UL);
|
||||
usb_wrpkt(&pdev->regs, pdev->host.hc[u8ChNum].xfer_buff, u8ChNum, u16Len, pdev->basic_cfgs.dmaen);
|
||||
pdev->host.hc[u8ChNum].xfer_buff += u16Len;
|
||||
pdev->host.hc[u8ChNum].xfer_len -= u16Len;
|
||||
pdev->host.hc[u8ChNum].xfer_count += u16Len;
|
||||
u32hptxsts = READ_REG32(pdev->regs.HREGS->HPTXSTS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function determines which interrupt conditions have occurred
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_port_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hprt;
|
||||
uint32_t u32hprt_bk;
|
||||
uint8_t u8fslspclksel;
|
||||
uint32_t do_reset = 0UL;
|
||||
uint8_t u8PortSpeed;
|
||||
|
||||
u32hprt = READ_REG32(*pdev->regs.HPRT);
|
||||
u32hprt_bk = u32hprt;
|
||||
/* Clear the interrupt bits in GINTSTS */
|
||||
//tmp_hprt_bk.b.prtovrcurrchng = 0U; //todo don't have this bit
|
||||
u32hprt_bk &= ~(USBFS_HPRT_PENA | USBFS_HPRT_PCDET | USBFS_HPRT_PENCHNG);
|
||||
|
||||
/* check if a port connect have been detected */
|
||||
if ((u32hprt & USBFS_HPRT_PCDET) != 0UL) {
|
||||
u32hprt_bk |= USBFS_HPRT_PCDET;
|
||||
if (host_driver_getvbusdrivestate(pdev) != 0UL) {
|
||||
pdev->host.is_dev_connect = 1U;
|
||||
}
|
||||
}
|
||||
/* check if port enable or disable change */
|
||||
if ((u32hprt & USBFS_HPRT_PENCHNG) != 0UL) {
|
||||
u32hprt_bk |= USBFS_HPRT_PENCHNG;
|
||||
|
||||
if ((u32hprt & USBFS_HPRT_PENA) != 0UL) {
|
||||
u8PortSpeed = (uint8_t)((u32hprt & USBFS_HPRT_PSPD) >> USBFS_HPRT_PSPD_POS);
|
||||
if ((u8PortSpeed == PRTSPD_LOW_SPEED) || (u8PortSpeed == PRTSPD_FULL_SPEED)) {
|
||||
u8fslspclksel = (uint8_t)(READ_REG32(pdev->regs.HREGS->HCFG) & USBFS_HCFG_FSLSPCS);
|
||||
if (u8PortSpeed == PRTSPD_LOW_SPEED) {
|
||||
if (u8fslspclksel != HCFG_6_MHZ) {
|
||||
do_reset = 1U;
|
||||
}
|
||||
} else {
|
||||
/* 1ms*(PHY clock frequency for FS/LS)-1 */
|
||||
WRITE_REG32(pdev->regs.HREGS->HFIR, 48000UL);
|
||||
if (u8fslspclksel != HCFG_48_MHZ) {
|
||||
usb_fslspclkselset(&pdev->regs, HCFG_48_MHZ);
|
||||
do_reset = 1U;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
do_reset = 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//todo don't have this bit
|
||||
//if ((u32hprt & USBFS_HPRT_PRTOVRCURRCHNG) != 0UL) {
|
||||
// u32hprt_bk |= USBFS_HPRT_PRTOVRCURRCHNG;
|
||||
//}
|
||||
|
||||
if (0UL != do_reset) {
|
||||
usb_hprtrst(&pdev->regs);
|
||||
}
|
||||
WRITE_REG32(*pdev->regs.HPRT, u32hprt_bk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief processes the rxFIFO non-empty interrupt
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_rxflvl_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32grxsts;
|
||||
uint32_t u32hctsiz;
|
||||
uint32_t u32hcchar;
|
||||
uint8_t u8chnum;
|
||||
uint8_t *pu8Tmp;
|
||||
uint16_t u16bcnt;
|
||||
|
||||
CLR_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_RXFNE);
|
||||
|
||||
u32grxsts = READ_REG32(pdev->regs.GREGS->GRXSTSP);
|
||||
u8chnum = (uint8_t)(u32grxsts & USBFS_GRXSTSP_CHNUM_EPNUM);
|
||||
u16bcnt = (uint16_t)((u32grxsts & USBFS_GRXSTSP_BCNT) >> USBFS_GRXSTSP_BCNT_POS);
|
||||
u32hcchar = READ_REG32(pdev->regs.HC_REGS[u8chnum]->HCCHAR);
|
||||
|
||||
switch ((u32grxsts & USBFS_GRXSTSP_PKTSTS) >> USBFS_GRXSTSP_PKTSTS_POS) {
|
||||
case 2: /* IN dat packet received */
|
||||
pu8Tmp = pdev->host.hc[u8chnum].xfer_buff;
|
||||
if ((u16bcnt > 0U) && (pu8Tmp != (void *)0U)) {
|
||||
usb_rdpkt(&pdev->regs, pdev->host.hc[u8chnum].xfer_buff, u16bcnt);
|
||||
pdev->host.hc[u8chnum].xfer_buff += u16bcnt;
|
||||
pdev->host.hc[u8chnum].xfer_count += u16bcnt;
|
||||
pdev->host.XferCnt[u8chnum] = pdev->host.hc[u8chnum].xfer_count;
|
||||
|
||||
u32hctsiz = READ_REG32(pdev->regs.HC_REGS[u8chnum]->HCTSIZ);
|
||||
if (((u32hctsiz & USBFS_HCTSIZ_PKTCNT) >> USBFS_HCTSIZ_PKTCNT_POS) > 0U) {
|
||||
u32hcchar |= USBFS_HCCHAR_CHENA;
|
||||
u32hcchar &= ~USBFS_HCCHAR_CHDIS;
|
||||
WRITE_REG32(pdev->regs.HC_REGS[u8chnum]->HCCHAR, u32hcchar);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* IN transfer completed(trigger an interrupt) */
|
||||
break;
|
||||
case 5: /* Daat toggle error(trigger an interrupt) */
|
||||
break;
|
||||
case 7: /* Channel halted(trigger an interrupt) */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SET_REG32_BIT(pdev->regs.GREGS->GINTMSK, USBFS_GINTSTS_RXFNE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief process the incomplete periodic transfer interrupt(incompIP)
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_incomplisoout_isr(usb_core_instance *pdev)
|
||||
{
|
||||
SET_REG32_BIT(pdev->regs.HC_REGS[0]->HCCHAR, USBFS_HCCHAR_CHENA | USBFS_HCCHAR_CHDIS);
|
||||
WRITE_REG32(pdev->regs.GREGS->GINTSTS, USBFS_GINTSTS_IPXFR_INCOMPISOOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief process the resume/remote wakeup detected interrupt(WkUpInt)
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
static void usb_host_wkupint_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t u32hprt;
|
||||
u32hprt = usb_rdhprt(&pdev->regs);
|
||||
u32hprt &= ~USBFS_HPRT_PRES;
|
||||
WRITE_REG32(*pdev->regs.HPRT, u32hprt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function process all interrupt of USB in host mode
|
||||
* @param [in] pdev device instance
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_isr(usb_core_instance *pdev)
|
||||
{
|
||||
uint32_t gintstsval;
|
||||
if (0U != usb_getcurmod(&pdev->regs)) {
|
||||
gintstsval = usb_getcoreintr(&pdev->regs);
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_SOF)) {
|
||||
usb_host_sof_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_RXFNE)) {
|
||||
usb_host_rxflvl_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_NPTXFE)) {
|
||||
usb_host_nptxfifoempty_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_PTXFE)) {
|
||||
usb_host_ptxfifoempty_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_HCINT)) {
|
||||
usb_host_hc_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_HPRTINT)) {
|
||||
usb_host_port_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_DISCINT)) {
|
||||
usb_host_disconn_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_IPXFR_INCOMPISOOUT)) {
|
||||
usb_host_incomplisoout_isr(pdev);
|
||||
}
|
||||
if (0UL != (gintstsval & USBFS_GINTSTS_WKUINT)) {
|
||||
usb_host_wkupint_isr(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_int.h
|
||||
* @brief Head file for usb_host_int.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_INT_H__
|
||||
#define __USB_HOST_INT_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define HCINT_NYET (1UL << 6)
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief clear the interrupt flag bit
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num the channel index
|
||||
* @param [in] intbit the interrupt bit of the register HCINTn
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void usb_host_clrint(usb_core_instance *pdev, uint32_t ch_num, uint32_t intbit)
|
||||
{
|
||||
WRITE_REG32(pdev->regs.HC_REGS[ch_num]->HCINT, intbit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mask the interrupt of ChHltd
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel index of the host application
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void usb_host_int_mskchhltd(usb_core_instance *pdev, uint32_t ch_num)
|
||||
{
|
||||
CLR_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_CHHM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unmask the interrupt of ChHltd
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel index of the host application
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void usb_host_int_unmskchhltd(usb_core_instance *pdev, uint32_t ch_num)
|
||||
{
|
||||
SET_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_CHHM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mask the interrupt of ACK
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel index of the host application
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void usb_host_int_mskack(usb_core_instance *pdev, uint32_t ch_num)
|
||||
{
|
||||
CLR_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_ACKM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unmask the interrupt of ACK
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] ch_num channel index of the host application
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void usb_host_int_unmskack(usb_core_instance *pdev, uint32_t ch_num)
|
||||
{
|
||||
SET_REG32_BIT(pdev->regs.HC_REGS[ch_num]->HCINTMSK, USBFS_HCINTMSK_ACKM);
|
||||
}
|
||||
|
||||
void usb_host_isr(usb_core_instance *pdev);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_INT_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,482 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_stdreq.c
|
||||
* @brief Standard requests for device enumeration
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_stdreq.h"
|
||||
#include "usb_host_ctrltrans.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes declared in the last part.
|
||||
******************************************************************************/
|
||||
void usb_host_parsedevdesc(usb_host_devdesc_typedef *, uint8_t *buf, uint16_t length);
|
||||
|
||||
void usb_host_parsecfgdesc(usb_host_cfgdesc_typedef *cfg_desc,
|
||||
usb_host_itfdesc_typedef *itf_desc,
|
||||
USB_HOST_EPDesc_TypeDef ep_desc[][USBH_MAX_NUM_ENDPOINTS],
|
||||
uint8_t *buf,
|
||||
uint16_t length);
|
||||
void usb_host_parseitfdesc(usb_host_itfdesc_typedef *if_descriptor, uint8_t *buf);
|
||||
void usb_host_parseepdesc(USB_HOST_EPDesc_TypeDef *ep_descriptor, uint8_t *buf);
|
||||
void usb_host_parsestringdesc(uint8_t *psrc, uint8_t *pdest, uint16_t length);
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief issue a command descriptor from the connected device. parses the
|
||||
* descriptor and updates the status once the response has been received.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] req_type type of the descriptor
|
||||
* @param [in] value_idx wValue of setup for the request to get Descriptr
|
||||
* @param [in] buff: buffer to save the the descriptor
|
||||
* @param [in] length the length of the description.
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_getdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t req_type,
|
||||
uint16_t value_idx,
|
||||
uint8_t *buff,
|
||||
uint16_t length)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_D2H | req_type;
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
|
||||
phost->ctrlparam.setup.b.wValue.w = value_idx;
|
||||
|
||||
if ((value_idx & 0xff00U) == USB_DESC_STRING) {
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0x0409U;
|
||||
} else {
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0U;
|
||||
}
|
||||
phost->ctrlparam.setup.b.wLength.w = length;
|
||||
return usb_host_ctrlreq(pdev, phost, buff, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue command to the device to get the device discription. it parses
|
||||
* the device descriptor and updates the status once getting the device
|
||||
* description.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set.
|
||||
* @param [in] length the length of the description.
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_getdevdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t length)
|
||||
{
|
||||
HOST_STATUS status;
|
||||
status = usb_host_getdesc(pdev,
|
||||
phost,
|
||||
(uint8_t)(USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD),
|
||||
USB_DESC_DEVICE,
|
||||
pdev->host.Rx_Buffer,
|
||||
(uint16_t)length);
|
||||
if (status == HSTATUS_OK) {
|
||||
/* Commands successfully sent and Response Received */
|
||||
usb_host_parsedevdesc(&phost->device_prop.devdesc, pdev->host.Rx_Buffer, (uint16_t)length);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue a command to get the configuration description from the device
|
||||
* connected, parse the configuration descriptor and update the
|
||||
* status once the response has been received.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set.
|
||||
* @param [in] length the length of the description.
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_getcfgdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint16_t length)
|
||||
{
|
||||
HOST_STATUS status;
|
||||
|
||||
status = usb_host_getdesc(pdev,
|
||||
phost,
|
||||
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
|
||||
USB_DESC_CONFIGURATION,
|
||||
pdev->host.Rx_Buffer,
|
||||
length);
|
||||
if (status == HSTATUS_OK) {
|
||||
usb_host_parsecfgdesc(&phost->device_prop.devcfgdesc,
|
||||
phost->device_prop.devitfdesc,
|
||||
phost->device_prop.devepdesc,
|
||||
pdev->host.Rx_Buffer,
|
||||
length);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issues string Descriptor command to the device. Once the response
|
||||
* received, it parses the string descriptor and updates the status.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] string_index the index for the string
|
||||
* @param [in] buff buffer to save the the string descriptor
|
||||
* @param [in] length the length of the description.
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_getstringdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t string_index,
|
||||
uint8_t *buff,
|
||||
uint16_t length)
|
||||
{
|
||||
HOST_STATUS status;
|
||||
status = usb_host_getdesc(pdev,
|
||||
phost,
|
||||
USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
|
||||
USB_DESC_STRING | string_index,
|
||||
pdev->host.Rx_Buffer,
|
||||
length);
|
||||
if (status == HSTATUS_OK) {
|
||||
usb_host_parsestringdesc(pdev->host.Rx_Buffer, buff, length);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue a command to set the address for the device that have connected.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] DeviceAddress Device address which would be set to the conected device
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_setdevaddr(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t DeviceAddress)
|
||||
{
|
||||
/*
|
||||
Refer to table9-3 of 9.4
|
||||
*/
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_ADDRESS;
|
||||
phost->ctrlparam.setup.b.wValue.w = (uint16_t)DeviceAddress;
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0U;
|
||||
phost->ctrlparam.setup.b.wLength.w = 0U;
|
||||
|
||||
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue a command to set the configuration to the connected device.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] cfg_idx value for the configuration setup
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_setconfig(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint16_t cfg_idx)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
|
||||
phost->ctrlparam.setup.b.wValue.w = cfg_idx;
|
||||
phost->ctrlparam.setup.b.wIndex.w = 0U;
|
||||
phost->ctrlparam.setup.b.wLength.w = 0U;
|
||||
|
||||
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue a command to set the Interface value to the connected device
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] ep_num the index of the endpoint
|
||||
* @param [in] altSetting the value for the setup of set interface
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_setintf(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t ep_num,
|
||||
uint8_t altSetting)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
|
||||
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_SET_INTERFACE;
|
||||
phost->ctrlparam.setup.b.wValue.w = altSetting;
|
||||
phost->ctrlparam.setup.b.wIndex.w = ep_num;
|
||||
phost->ctrlparam.setup.b.wLength.w = 0U;
|
||||
|
||||
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief issue a comman to clear or disable a specific feature in the device.
|
||||
* @param [in] pdev device instance
|
||||
* @param [in] phost host state set
|
||||
* @param [in] ep_num index of the endpoint
|
||||
* @param [in] hc_num host channel index
|
||||
* @retval status
|
||||
*/
|
||||
HOST_STATUS usb_host_clrfeature(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t ep_num,
|
||||
uint8_t hc_num)
|
||||
{
|
||||
phost->ctrlparam.setup.b.bmRequestType = USB_H2D |
|
||||
USB_REQ_RECIPIENT_ENDPOINT |
|
||||
USB_REQ_TYPE_STANDARD;
|
||||
|
||||
phost->ctrlparam.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
|
||||
phost->ctrlparam.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
|
||||
phost->ctrlparam.setup.b.wIndex.w = ep_num;
|
||||
phost->ctrlparam.setup.b.wLength.w = 0U;
|
||||
|
||||
if ((ep_num & USB_REQ_DIR_MASK) == USB_D2H) {
|
||||
pdev->host.hc[hc_num].in_toggle = 0U;
|
||||
} else {
|
||||
pdev->host.hc[hc_num].out_toggle = 0U;
|
||||
}
|
||||
|
||||
return usb_host_ctrlreq(pdev, phost, NULL, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief parse the data frame of device descriptor
|
||||
* @param [in] dev_desc the structure of the device descriptor
|
||||
* @param [in] buf buffer where the source descriptor is save
|
||||
* @param [in] length Length of the descriptor in byte
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_parsedevdesc(usb_host_devdesc_typedef *dev_desc,
|
||||
uint8_t *buf,
|
||||
uint16_t length)
|
||||
{
|
||||
dev_desc->bLength = *(uint8_t *)(buf + 0U);
|
||||
dev_desc->bDescriptorType = *(uint8_t *)(buf + 1U);
|
||||
dev_desc->bcdUSB = SMALL_END(buf + 2U);
|
||||
dev_desc->bDeviceClass = *(uint8_t *)(buf + 4U);
|
||||
dev_desc->bDeviceSubClass = *(uint8_t *)(buf + 5U);
|
||||
dev_desc->bDeviceProtocol = *(uint8_t *)(buf + 6U);
|
||||
dev_desc->bMaxPacketSize0 = *(uint8_t *)(buf + 7U);
|
||||
|
||||
if (length > (uint16_t)8) {
|
||||
dev_desc->idVendor = SMALL_END(buf + 8U);
|
||||
dev_desc->idProduct = SMALL_END(buf + 10U);
|
||||
dev_desc->bcdDevice = SMALL_END(buf + 12U);
|
||||
dev_desc->iManufacturer = *(uint8_t *)(buf + 14U);
|
||||
dev_desc->iProduct = *(uint8_t *)(buf + 15U);
|
||||
dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U);
|
||||
dev_desc->bNumConfigurations = *(uint8_t *)(buf + 17U);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function Parses the configuration descriptor from the received buffer
|
||||
* @param [in] cfg_desc the structure of configuration descriptor
|
||||
* @param [in] itf_desc the structure of interface descriptor
|
||||
* @param [in] ep_desc the structure of endpoint descriptor
|
||||
* @param [in] buf buffer where the source descriptor is save
|
||||
* @param [in] length Length of the descriptor in byte
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_parsecfgdesc(usb_host_cfgdesc_typedef *cfg_desc,
|
||||
usb_host_itfdesc_typedef *itf_desc,
|
||||
USB_HOST_EPDesc_TypeDef ep_desc[][USBH_MAX_NUM_ENDPOINTS],
|
||||
uint8_t *buf,
|
||||
uint16_t length)
|
||||
{
|
||||
usb_host_itfdesc_typedef *pif ;
|
||||
usb_host_itfdesc_typedef temp_pif ;
|
||||
USB_HOST_EPDesc_TypeDef *pep;
|
||||
USB_HOST_DescHeader_TypeDef *pdesc = (USB_HOST_DescHeader_TypeDef *)buf;
|
||||
uint16_t ptr;
|
||||
int8_t if_ix;
|
||||
int8_t ep_ix;
|
||||
static uint16_t prev_ep_size = 0U;
|
||||
static uint8_t prev_itf = 0U;
|
||||
|
||||
/* Parse the configuration descriptor */
|
||||
cfg_desc->bLength = *(uint8_t *)(buf + 0U);
|
||||
cfg_desc->bDescriptorType = *(uint8_t *)(buf + 1U);
|
||||
cfg_desc->wTotalLength = SMALL_END(buf + 2U);
|
||||
cfg_desc->bNumInterfaces = *(uint8_t *)(buf + 4U);
|
||||
cfg_desc->bConfigurationValue = *(uint8_t *)(buf + 5U);
|
||||
cfg_desc->iConfiguration = *(uint8_t *)(buf + 6U);
|
||||
cfg_desc->bmAttributes = *(uint8_t *)(buf + 7U);
|
||||
cfg_desc->bMaxPower = *(uint8_t *)(buf + 8U);
|
||||
|
||||
if (length > USB_CONFIGURATION_DESC_SIZE) {
|
||||
ptr = USB_LEN_CFG_DESC;
|
||||
|
||||
if (cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES) {
|
||||
|
||||
while (ptr < cfg_desc->wTotalLength) {
|
||||
pdesc = usb_host_getnextdesc((uint8_t *)pdesc, &ptr);
|
||||
if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE) {
|
||||
if_ix = (int8_t) * (((uint8_t *)pdesc) + 2U);
|
||||
pif = &itf_desc[if_ix];
|
||||
|
||||
if ((*((uint8_t *)pdesc + 3U)) < 3U) {
|
||||
usb_host_parseitfdesc(&temp_pif, (uint8_t *)pdesc);
|
||||
ep_ix = (int8_t)0;
|
||||
|
||||
/* Parse Ep descriptors relative to the current interface */
|
||||
if (temp_pif.bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) {
|
||||
while (ep_ix < (int8_t)temp_pif.bNumEndpoints) {
|
||||
pdesc = usb_host_getnextdesc((void *)pdesc, &ptr);
|
||||
if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT) {
|
||||
pep = &ep_desc[if_ix][ep_ix];
|
||||
|
||||
if (prev_itf != (uint8_t)if_ix) {
|
||||
prev_itf = (uint8_t)if_ix;
|
||||
usb_host_parseitfdesc(pif, (uint8_t *)&temp_pif);
|
||||
} else {
|
||||
if (prev_ep_size > SMALL_END((uint8_t *)pdesc + 4U)) {
|
||||
break;
|
||||
} else {
|
||||
usb_host_parseitfdesc(pif, (uint8_t *)&temp_pif);
|
||||
}
|
||||
}
|
||||
usb_host_parseepdesc(pep, (uint8_t *)pdesc);
|
||||
prev_ep_size = SMALL_END((uint8_t *)pdesc + 4U);
|
||||
ep_ix++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_ep_size = 0U;
|
||||
prev_itf = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses the interface descriptor from the received buffer.
|
||||
* @param [in] if_descriptor structure of interface descriptor
|
||||
* @param [in] buf buffer where the source descriptor is save
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_parseitfdesc(usb_host_itfdesc_typedef *if_descriptor, uint8_t *buf)
|
||||
{
|
||||
if_descriptor->bLength = *(uint8_t *)(buf + 0U);
|
||||
if_descriptor->bDescriptorType = *(uint8_t *)(buf + 1U);
|
||||
if_descriptor->bInterfaceNumber = *(uint8_t *)(buf + 2U);
|
||||
if_descriptor->bAlternateSetting = *(uint8_t *)(buf + 3U);
|
||||
if_descriptor->bNumEndpoints = *(uint8_t *)(buf + 4U);
|
||||
if_descriptor->bInterfaceClass = *(uint8_t *)(buf + 5U);
|
||||
if_descriptor->bInterfaceSubClass = *(uint8_t *)(buf + 6U);
|
||||
if_descriptor->bInterfaceProtocol = *(uint8_t *)(buf + 7U);
|
||||
if_descriptor->iInterface = *(uint8_t *)(buf + 8U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses the endpoint descriptor from the received buffer.
|
||||
* @param [in] ep_descriptor the structure of endpoint descriptor.
|
||||
* @param [in] buf buffer where the source descriptor is save
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_parseepdesc(USB_HOST_EPDesc_TypeDef *ep_descriptor, uint8_t *buf)
|
||||
{
|
||||
ep_descriptor->bLength = *(uint8_t *)(buf + 0U);
|
||||
ep_descriptor->bDescriptorType = *(uint8_t *)(buf + 1U);
|
||||
ep_descriptor->bEndpointAddress = *(uint8_t *)(buf + 2U);
|
||||
ep_descriptor->bmAttributes = *(uint8_t *)(buf + 3U);
|
||||
ep_descriptor->wMaxPacketSize = SMALL_END(buf + 4U);
|
||||
ep_descriptor->bInterval = *(uint8_t *)(buf + 6U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses the string descriptor from the received buffer.
|
||||
* @param [in] psrc source data
|
||||
* @param [in] pdest destination data
|
||||
* @param [in] length Length of the descriptor in byte
|
||||
* @retval None
|
||||
*/
|
||||
void usb_host_parsestringdesc(uint8_t *psrc, uint8_t *pdest, uint16_t length)
|
||||
{
|
||||
uint16_t strlength;
|
||||
uint16_t tmp_idx;
|
||||
/*
|
||||
The describ of String Desctipor refers to 9.6.8
|
||||
psrc[0] = bLength bLength = N+2
|
||||
psrc[1] = bDescriptorType STRING Descriptor Type
|
||||
...
|
||||
*/
|
||||
if (psrc[1] == USB_DESC_TYPE_STRING) {
|
||||
strlength = ((((uint16_t)psrc[0]) - 2U) <= length) ? (((uint16_t)psrc[0]) - 2U) : length;
|
||||
psrc += 2U;
|
||||
for (tmp_idx = 0U; tmp_idx < strlength; tmp_idx += 2U) {
|
||||
*pdest = psrc[tmp_idx];
|
||||
pdest++;
|
||||
}
|
||||
*pdest = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets the header of next descriptor.
|
||||
* @param [in] pbuf buffer where the configuration descriptor is contained.
|
||||
* @param [in] ptr data popinter inside the cfg descriptor
|
||||
* @retval header of next descriptor
|
||||
*/
|
||||
USB_HOST_DescHeader_TypeDef *usb_host_getnextdesc(uint8_t *pbuf, uint16_t *ptr)
|
||||
{
|
||||
USB_HOST_DescHeader_TypeDef *pnext;
|
||||
|
||||
*ptr += ((USB_HOST_DescHeader_TypeDef *)pbuf)->bLength;
|
||||
pnext = (USB_HOST_DescHeader_TypeDef *)((uint8_t *)pbuf + ((USB_HOST_DescHeader_TypeDef *)pbuf)->bLength);
|
||||
|
||||
return (pnext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* EOF (not truncated)
|
||||
*****************************************************************************/
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_host_stdreq.h
|
||||
* @brief Header file for usb_host_stdreq.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_STDREQ_H__
|
||||
#define __USB_HOST_STDREQ_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include "usb_host_def.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_HOST_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/* USBH_STDREQ_Exported_Defines */
|
||||
/* Standard Feature Selector for clear feature command */
|
||||
#define FEATURE_SELECTOR_ENDPOINT (0x00U)
|
||||
#define FEATURE_SELECTOR_DEVICE (0x01U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern HOST_STATUS usb_host_getdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t req_type,
|
||||
uint16_t value_idx,
|
||||
uint8_t *buff,
|
||||
uint16_t length);
|
||||
|
||||
extern HOST_STATUS usb_host_getdevdesc(usb_core_instance *pdev, USBH_HOST *phost, uint8_t length);
|
||||
|
||||
HOST_STATUS usb_host_getstringdesc(usb_core_instance *pdev,
|
||||
USBH_HOST *phost,
|
||||
uint8_t string_index,
|
||||
uint8_t *buff,
|
||||
uint16_t length);
|
||||
|
||||
extern HOST_STATUS usb_host_setconfig(usb_core_instance *pdev, USBH_HOST *phost, uint16_t cfg_idx);
|
||||
|
||||
extern HOST_STATUS usb_host_getcfgdesc(usb_core_instance *pdev, USBH_HOST *phost, uint16_t length);
|
||||
|
||||
extern HOST_STATUS usb_host_setdevaddr(usb_core_instance *pdev, USBH_HOST *phost, uint8_t DeviceAddress);
|
||||
|
||||
extern HOST_STATUS usb_host_clrfeature(usb_core_instance *pdev, USBH_HOST *phost, uint8_t ep_num, uint8_t hc_num);
|
||||
|
||||
extern HOST_STATUS usb_host_setintf(usb_core_instance *pdev, USBH_HOST *phost, uint8_t ep_num, uint8_t altSetting);
|
||||
|
||||
extern USB_HOST_DescHeader_TypeDef *usb_host_getnextdesc(uint8_t *pbuf, uint16_t *ptr);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_HOST_STDREQ_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb_lib.h
|
||||
* @brief Header of the Core Layer Driver
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_LIB_H__
|
||||
#define __USB_LIB_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <hc32_ll_usb.h>
|
||||
#include <hc32_ll.h>
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB LL USB Lib
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LL_USB_LIB_DEF LL USB Lib Define
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define MAX_DATA_LENGTH (0x200U)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/* status of the host channel */
|
||||
typedef enum {
|
||||
HOST_CH_IDLE = 0U,
|
||||
HOST_CH_XFERCOMPL,
|
||||
HOST_CH_CHHLTD,
|
||||
HOST_CH_NAK,
|
||||
HOST_CH_NYET,
|
||||
HOST_CH_STALL,
|
||||
HOST_CH_XACTERR,
|
||||
HOST_CH_BBLERR,
|
||||
HOST_CH_DATATGLERR,
|
||||
HOST_CH_AHBERR,
|
||||
HOST_CH_FRMOVRUN,
|
||||
HOST_CH_BNAINTR,
|
||||
HOST_CH_XCS_XACT_ERR,
|
||||
HOST_CH_DESC_LST_ROLLINTR
|
||||
} HOST_CH_STATUS;
|
||||
|
||||
typedef enum {
|
||||
HOST_CH_XFER_IDLE = 0U,
|
||||
HOST_CH_XFER_DONE,
|
||||
HOST_CH_XFER_UNREADY,
|
||||
HOST_CH_XFER_ERROR,
|
||||
HOST_CH_XFER_STALL
|
||||
} HOST_CH_XFER_STATE;
|
||||
|
||||
typedef enum {
|
||||
CTRL_START = 0U,
|
||||
CTRL_XFRC,
|
||||
CTRL_HALTED,
|
||||
CTRL_NAK,
|
||||
CTRL_STALL,
|
||||
CTRL_XACTERR,
|
||||
CTRL_BBLERR,
|
||||
CTRL_DATATGLERR,
|
||||
CTRL_FAIL
|
||||
} CTRL_HANDLE_STATUS;
|
||||
|
||||
typedef struct {
|
||||
uint8_t bmRequest;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} USB_SETUP_REQ;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *(*get_dev_desc)(uint16_t *length);
|
||||
uint8_t *(*get_dev_langiddesc)(uint16_t *length);
|
||||
uint8_t *(*get_dev_manufacturerstr)(uint16_t *length);
|
||||
uint8_t *(*get_dev_productstr)(uint16_t *length);
|
||||
uint8_t *(*get_dev_serialstr)(uint16_t *length);
|
||||
uint8_t *(*get_dev_configstr)(uint16_t *length);
|
||||
uint8_t *(*get_dev_interfacestr)(uint16_t *length);
|
||||
} usb_dev_desc_func;
|
||||
|
||||
typedef struct {
|
||||
void (*class_init)(void *pdev);
|
||||
void (*class_deinit)(void *pdev);
|
||||
uint8_t (*ep0_setup)(void *pdev, USB_SETUP_REQ *req);
|
||||
void (*ep0_datain)(void *pdev);
|
||||
void (*ep0_dataout)(void *pdev);
|
||||
uint8_t *(*class_getconfigdesc)(uint16_t *length);
|
||||
uint8_t (*class_sof)(void *pdev);
|
||||
void (*class_datain)(void *pdev, uint8_t epnum);
|
||||
void (*class_dataout)(void *pdev, uint8_t epnum);
|
||||
void (*class_syn_in_incomplt)(void *pdev);
|
||||
void (*class_syn_out_incomplt)(void *pdev);
|
||||
} usb_dev_class_func;
|
||||
|
||||
typedef struct {
|
||||
void (*user_init)(void);
|
||||
void (*user_devrst)(void);
|
||||
void (*user_devconfig)(void);
|
||||
void (*user_devsusp)(void);
|
||||
void (*user_devresume)(void);
|
||||
void (*user_devconn)(void);
|
||||
void (*user_devdisconn)(void);
|
||||
} usb_dev_user_func;
|
||||
|
||||
typedef struct {
|
||||
__IO uint8_t device_config;
|
||||
__IO uint8_t device_address;
|
||||
__IO uint8_t device_state;
|
||||
__IO uint8_t device_old_status;
|
||||
__IO uint8_t device_cur_status;
|
||||
__IO uint8_t connection_status;
|
||||
__IO uint8_t device_remote_wakeup;
|
||||
__IO uint8_t test_mode;
|
||||
USB_DEV_EP in_ep[USB_MAX_TX_FIFOS];
|
||||
USB_DEV_EP out_ep[USB_MAX_TX_FIFOS];
|
||||
uint8_t setup_pkt_buf[24];
|
||||
usb_dev_class_func *class_callback;
|
||||
usb_dev_user_func *user_callback;
|
||||
usb_dev_desc_func *desc_callback;
|
||||
} USB_DEV_PARAM;
|
||||
|
||||
typedef struct {
|
||||
uint16_t channel[USB_MAX_TX_FIFOS];
|
||||
USB_HOST_CH hc[USB_MAX_TX_FIFOS];
|
||||
__IO uint32_t is_dev_connect;
|
||||
uint8_t Rx_Buffer[MAX_DATA_LENGTH];
|
||||
__IO uint32_t ErrCnt[USB_MAX_TX_FIFOS];
|
||||
__IO uint32_t XferCnt[USB_MAX_TX_FIFOS];
|
||||
__IO HOST_CH_STATUS HC_Status[USB_MAX_TX_FIFOS];
|
||||
__IO HOST_CH_XFER_STATE URB_State[USB_MAX_TX_FIFOS];
|
||||
} USB_HOST_PARAM;
|
||||
|
||||
typedef struct {
|
||||
USB_CORE_BASIC_CFGS basic_cfgs;
|
||||
LL_USB_TypeDef regs;
|
||||
#ifdef USE_DEVICE_MODE
|
||||
USB_DEV_PARAM dev;
|
||||
#endif
|
||||
#ifdef USE_HOST_MODE
|
||||
USB_HOST_PARAM host;
|
||||
#endif
|
||||
} usb_core_instance;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USB_LIB_H__ */
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb/usb_host_msc/source/usb_host_user.c
|
||||
* @brief user application layer.
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file usb_host_user.c
|
||||
* @brief support hc32f4a0-board usb function
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-11-07
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: usb_host_user.c
|
||||
Description: support hc32f4a0-board usb function
|
||||
Others:
|
||||
History:
|
||||
1. Date: 2022-11-07
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
1. delete useless usb host configure and define
|
||||
2. add KPrintf function
|
||||
3. add UsbMountFileSystem() and UsbUnmountFileSystem()
|
||||
*************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <device.h>
|
||||
#include "usb_host_user.h"
|
||||
#include "usb_host_msc_class.h"
|
||||
#include "usb_host_msc_scsi.h"
|
||||
#include "usb_host_msc_bot.h"
|
||||
#include "usb_host_driver.h"
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Applications
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup USB_Host_Msc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
extern void UsbMountFileSystem();
|
||||
extern void UsbUnmountFileSystem();
|
||||
|
||||
/* USBH_USR_Private_Macros */
|
||||
extern usb_core_instance usb_app_instance;
|
||||
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
usb_host_user_callback_func USR_cb = {
|
||||
&host_user_init,
|
||||
&host_user_denint,
|
||||
&host_user_devattached,
|
||||
&host_user_devreset,
|
||||
&host_user_devdisconn,
|
||||
&host_user_overcurrent,
|
||||
&host_user_devspddetected,
|
||||
&host_user_devdescavailable,
|
||||
&host_user_devaddrdistributed,
|
||||
&host_user_cfgdescavailable,
|
||||
&host_user_mfcstring,
|
||||
&host_user_productstring,
|
||||
&host_user_serialnum,
|
||||
&host_user_enumcompl,
|
||||
&host_user_userinput,
|
||||
&host_user_msc_app,
|
||||
&host_user_devunsupported,
|
||||
&host_user_unrecoverederror
|
||||
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Local function prototypes ('static')
|
||||
******************************************************************************/
|
||||
static int usb_connect_status = 0;
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
uint8_t USB_HOST_USER_AppState = USH_USR_FS_INIT;
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief Displays the message on terminal for host lib initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_init(void)
|
||||
{
|
||||
static uint8_t startup = 0U;
|
||||
|
||||
if (startup == 0U) {
|
||||
startup = 1U;
|
||||
//KPrintf("USB Host library v2.1.0 started\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on terminal via DDL_Printf
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devattached(void)
|
||||
{
|
||||
KPrintf("USB device attached\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief host_user_unrecoverederror
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_unrecoverederror(void)
|
||||
{
|
||||
KPrintf("USB device unrecovered error\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Device disconnect event
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devdisconn(void)
|
||||
{
|
||||
KPrintf("USB device disconnect\r\n");
|
||||
usb_connect_status = 0;
|
||||
UsbUnmountFileSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBH_USR_ResetUSBDevice
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devreset(void)
|
||||
{
|
||||
/* callback for USB-Reset */
|
||||
KPrintf("USB device reset\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief host_user_devspddetected
|
||||
* @param [in] DeviceSpeed USB speed
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devspddetected(uint8_t DeviceSpeed)
|
||||
{
|
||||
if (DeviceSpeed == PRTSPD_FULL_SPEED) {
|
||||
KPrintf("USB device speed PRTSPD_FULL_SPEED\r\n");
|
||||
} else if (DeviceSpeed == PRTSPD_LOW_SPEED) {
|
||||
KPrintf("USB device speed PRTSPD_LOW_SPEED\r\n");
|
||||
} else {
|
||||
KPrintf("USB device speed error\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief host_user_devdescavailable
|
||||
* @param [in] DeviceDesc device descriptor
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devdescavailable(void *DeviceDesc)
|
||||
{
|
||||
usb_host_devdesc_typedef *hs;
|
||||
hs = DeviceDesc;
|
||||
KPrintf("USB device VID : %04lXh PID : %04lXh\r\n", (uint32_t)(*hs).idVendor, (uint32_t)(*hs).idProduct);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief host_user_devaddrdistributed
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devaddrdistributed(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief host_user_cfgdescavailable
|
||||
* @param [in] cfgDesc Configuration desctriptor
|
||||
* @param [in] itfDesc Interface desctriptor
|
||||
* @param [in] epDesc Endpoint desctriptor
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_cfgdescavailable(usb_host_cfgdesc_typedef *cfgDesc,
|
||||
usb_host_itfdesc_typedef *itfDesc,
|
||||
USB_HOST_EPDesc_TypeDef *epDesc)
|
||||
{
|
||||
usb_host_itfdesc_typedef *id;
|
||||
|
||||
id = itfDesc;
|
||||
if ((*id).bInterfaceClass == 0x08U) {
|
||||
KPrintf("USB Mass storage device connected\r\n");
|
||||
} else if ((*id).bInterfaceClass == 0x03U) {
|
||||
KPrintf("USB HID device connected\r\n");
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on terminal for Manufacturer String
|
||||
* @param [in] ManufacturerString
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_mfcstring(void *ManufacturerString)
|
||||
{
|
||||
KPrintf("Manufacturer : %s\r\n", (char *)ManufacturerString);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on terminal for product String
|
||||
* @param [in] ProductString
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_productstring(void *ProductString)
|
||||
{
|
||||
KPrintf("Product : %s\r\n", (char *)ProductString);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on terminal for SerialNum_String
|
||||
* @param [in] SerialNumString
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_serialnum(void *SerialNumString)
|
||||
{
|
||||
KPrintf("Serial Number : %s\r\n", (char *)SerialNumString);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief User response request is displayed to ask application jump to class
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_enumcompl(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Device is not supported
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_devunsupported(void)
|
||||
{
|
||||
KPrintf("USB Device not supported.\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief User Action for application state entry
|
||||
* @param None
|
||||
* @retval HOST_USER_STATUS User response for key button
|
||||
*/
|
||||
HOST_USER_STATUS host_user_userinput(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Over Current Detected on VBUS
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_overcurrent(void)
|
||||
{
|
||||
KPrintf("USB HOST Overcurrent detected.\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Demo application for mass storage
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
int host_user_msc_app(void)
|
||||
{
|
||||
if (0 == usb_connect_status) {
|
||||
KPrintf("ready to mount file system\n");
|
||||
UsbMountFileSystem();
|
||||
usb_connect_status = 1;
|
||||
}
|
||||
|
||||
return ((int)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deint User state and associated variables
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void host_user_denint(void)
|
||||
{
|
||||
USB_HOST_USER_AppState = USH_USR_FS_INIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
*******************************************************************************
|
||||
* @file usb/usb_host_msc/source/usb_host_user.h
|
||||
* @brief Header file for usb_host_user.c
|
||||
@verbatim
|
||||
Change Logs:
|
||||
Date Author Notes
|
||||
2022-03-31 CDT First version
|
||||
@endverbatim
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by XHSC under BSD 3-Clause license
|
||||
* (the "License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef __USB_HOST_USER_H__
|
||||
#define __USB_HOST_USER_H__
|
||||
|
||||
/* C binding of definitions if building with C++ compiler */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Include files
|
||||
******************************************************************************/
|
||||
//#include "ff.h"
|
||||
#include "usb_host_core.h"
|
||||
#include "usb_app_conf.h"
|
||||
#include <stdio.h>
|
||||
#include "usb_host_msc_class.h"
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Applications
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup USB_Host_Msc
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Global pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
/* State Machine for the USBH_USR_ApplicationState */
|
||||
#define USH_USR_FS_INIT (0U)
|
||||
#define USH_USR_FS_READLIST (1U)
|
||||
#define USH_USR_FS_WRITEFILE (2U)
|
||||
#define USH_USR_FS_IDLE (3U)
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions ('extern')
|
||||
******************************************************************************/
|
||||
extern usb_host_user_callback_func USR_cb;
|
||||
extern uint8_t USB_HOST_USER_AppState;
|
||||
|
||||
/*******************************************************************************
|
||||
Global function prototypes (definition in C source)
|
||||
******************************************************************************/
|
||||
extern void host_user_init(void);
|
||||
extern void host_user_denint(void);
|
||||
extern void host_user_devattached(void);
|
||||
extern void host_user_devreset(void);
|
||||
extern void host_user_devdisconn(void);
|
||||
extern void host_user_overcurrent(void);
|
||||
extern void host_user_devspddetected(uint8_t DeviceSpeed);
|
||||
extern void host_user_devdescavailable(void *DeviceDesc);
|
||||
extern void host_user_devaddrdistributed(void);
|
||||
extern void host_user_cfgdescavailable(usb_host_cfgdesc_typedef *cfgDesc,
|
||||
usb_host_itfdesc_typedef *itfDesc,
|
||||
USB_HOST_EPDesc_TypeDef *epDesc);
|
||||
extern void host_user_mfcstring(void *ManufacturerString);
|
||||
extern void host_user_productstring(void *ProductString);
|
||||
extern void host_user_serialnum(void *SerialNumString);
|
||||
extern void host_user_enumcompl(void);
|
||||
extern HOST_USER_STATUS host_user_userinput(void);
|
||||
extern void host_user_devunsupported(void);
|
||||
extern void host_user_unrecoverederror(void);
|
||||
extern int host_user_msc_app(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__USB_HOST_USER_H__*/
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF (not truncated)
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ menu "imxrt1176-sbc feature"
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool "mount cd card"
|
||||
bool "mount sd card"
|
||||
default n
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -391,9 +391,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device2;
|
||||
memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2;
|
||||
static struct SpiSlaveParam spi_slaveparam2;
|
||||
memset(&spi_slaveparam2, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam2.spi_slave_id = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_slaveparam2.spi_cs_gpio_pin = SPI1_CS2_PIN;
|
||||
spi_slaveparam2.spi_cs_select_id = SPI_CHIP_SELECT_2;
|
||||
|
||||
spi_device2.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device2.spi_param.spi_slave_param = &spi_slaveparam2;
|
||||
|
||||
spi_device2.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
@@ -414,9 +420,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device3;
|
||||
memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3;
|
||||
static struct SpiSlaveParam spi_slaveparam3;
|
||||
memset(&spi_slaveparam3, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam3.spi_slave_id = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_slaveparam3.spi_cs_gpio_pin = SPI1_CS3_PIN;
|
||||
spi_slaveparam3.spi_cs_select_id = SPI_CHIP_SELECT_3;
|
||||
|
||||
spi_device3.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device3.spi_param.spi_slave_param = &spi_slaveparam3;
|
||||
|
||||
spi_device3.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ menu "kd233 feature"
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool "mount cd card"
|
||||
bool "mount sd card"
|
||||
default n
|
||||
select BSP_USING_SPI
|
||||
select BSP_USING_SPI1
|
||||
|
||||
@@ -393,9 +393,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device2;
|
||||
memset(&spi_device2, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_2] = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_2] = SPI1_CS2_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_2] = SPI_CHIP_SELECT_2;
|
||||
static struct SpiSlaveParam spi_slaveparam2;
|
||||
memset(&spi_slaveparam2, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam2.spi_slave_id = SPI_DEVICE_SLAVE_ID_2;
|
||||
spi_slaveparam2.spi_cs_gpio_pin = SPI1_CS2_PIN;
|
||||
spi_slaveparam2.spi_cs_select_id = SPI_CHIP_SELECT_2;
|
||||
|
||||
spi_device2.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device2.spi_param.spi_slave_param = &spi_slaveparam2;
|
||||
|
||||
spi_device2.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
@@ -416,9 +422,15 @@ static int BoardSpiDevBend(struct SpiDmaParam *spi_initparam)
|
||||
static struct SpiHardwareDevice spi_device3;
|
||||
memset(&spi_device3, 0, sizeof(struct SpiHardwareDevice));
|
||||
|
||||
spi_initparam->spi_slave_id[SPI_DEVICE_SLAVE_ID_3] = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_initparam->spi_cs_gpio_pin[SPI_DEVICE_SLAVE_ID_3] = SPI1_CS3_PIN;
|
||||
spi_initparam->spi_cs_select_id[SPI_DEVICE_SLAVE_ID_3] = SPI_CHIP_SELECT_3;
|
||||
static struct SpiSlaveParam spi_slaveparam3;
|
||||
memset(&spi_slaveparam3, 0, sizeof(struct SpiSlaveParam));
|
||||
|
||||
spi_slaveparam3.spi_slave_id = SPI_DEVICE_SLAVE_ID_3;
|
||||
spi_slaveparam3.spi_cs_gpio_pin = SPI1_CS3_PIN;
|
||||
spi_slaveparam3.spi_cs_select_id = SPI_CHIP_SELECT_3;
|
||||
|
||||
spi_device3.spi_param.spi_dma_param = spi_initparam;
|
||||
spi_device3.spi_param.spi_slave_param = &spi_slaveparam3;
|
||||
|
||||
spi_device3.spi_dev_done = &(spi_dev_done);
|
||||
|
||||
|
||||
@@ -42,7 +42,10 @@ menu "ok1052-c feature"
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool "mount cd card"
|
||||
bool
|
||||
default n
|
||||
config MOUNT_USB
|
||||
bool
|
||||
default n
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ extern int ExtSramInit(void);
|
||||
#include <connect_uart.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_USB
|
||||
#include <connect_usb.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_ADC
|
||||
#include <connect_adc.h>
|
||||
#endif
|
||||
@@ -693,5 +697,11 @@ void InitBoardHardware()
|
||||
Imxrt1052HwSdioInit();
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_USB
|
||||
#ifdef BSP_USING_NXP_USBH
|
||||
Imxrt1052HwUsbHostInit();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ if BSP_USING_SDIO
|
||||
default "sdio_dev"
|
||||
|
||||
config MOUNT_SDCARD_FS
|
||||
bool "mount cd card file system"
|
||||
bool "mount sd card file system"
|
||||
default n
|
||||
select MOUNT_SDCARD
|
||||
|
||||
|
||||
@@ -11,5 +11,15 @@ config BSP_USING_NXP_USBH
|
||||
config USB_DEVICE_NAME
|
||||
string "usb bus device name"
|
||||
default "usb_dev"
|
||||
config MOUNT_USB_FS
|
||||
bool "mount usb file system"
|
||||
default y
|
||||
select MOUNT_USB
|
||||
|
||||
if MOUNT_USB_FS
|
||||
config MOUNT_USB_FS_TYPE
|
||||
int "choose file system type : FATFS(0) LWEXT4(3)"
|
||||
default 0
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -28,13 +28,14 @@ Modification:
|
||||
#include <board.h>
|
||||
#include <connect_usb.h>
|
||||
|
||||
#define BSP_USING_NXP_USBH
|
||||
#ifdef BSP_USING_NXP_USBH
|
||||
|
||||
/*! @brief USB host msd command instance global variable */
|
||||
extern usb_host_msd_command_instance_t g_MsdCommandInstance;
|
||||
usb_host_handle g_HostHandle;
|
||||
|
||||
static void UsbHostTask(void* parameter);
|
||||
|
||||
extern usb_status_t USB_HostMsdReadApi(usb_host_msd_command_instance_t *msdCommandInstance, uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num);
|
||||
extern usb_status_t USB_HostMsdWriteApi(usb_host_msd_command_instance_t *msdCommandInstance, const uint8_t *buffer, uint32_t pos, uint32_t block_size, uint32_t block_num);
|
||||
|
||||
@@ -149,6 +150,22 @@ void UsbUnmountFileSystem()
|
||||
{
|
||||
UnmountFileSystem(UDISK_MOUNTPOINT);
|
||||
}
|
||||
|
||||
#ifdef MOUNT_USB
|
||||
int MountUsb(void)
|
||||
{
|
||||
int32 usb_host_task = 0;
|
||||
usb_host_task = KTaskCreate("usbh", UsbHostTask, NONE,
|
||||
USB_HOST_STACK_SIZE, 8);
|
||||
if(usb_host_task < 0) {
|
||||
KPrintf("usb_host_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
StartupKTask(usb_host_task);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint32 UsbHostOpen(void *dev)
|
||||
@@ -259,7 +276,6 @@ static int BoardUsbDevBend(void)
|
||||
int Imxrt1052HwUsbHostInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
int32 usb_host_task = 0;
|
||||
|
||||
static struct UsbBus usb_bus;
|
||||
memset(&usb_bus, 0, sizeof(struct UsbBus));
|
||||
@@ -281,15 +297,6 @@ int Imxrt1052HwUsbHostInit(void)
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
usb_host_task = KTaskCreate("usbh", UsbHostTask, NONE,
|
||||
USB_HOST_STACK_SIZE, 8);
|
||||
if(usb_host_task < 0) {
|
||||
KPrintf("usb_host_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
StartupKTask(usb_host_task);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,14 @@ menu "stm32f407-st-discovery feature"
|
||||
default 0x20000000
|
||||
endmenu
|
||||
|
||||
menu "config board peripheral"
|
||||
config MOUNT_SDCARD
|
||||
bool
|
||||
default n
|
||||
config MOUNT_USB
|
||||
bool
|
||||
default n
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -50,6 +50,7 @@ extern int Stm32HwRtcInit();
|
||||
extern int HwSdioInit();
|
||||
extern int Stm32HwAdcInit(void);
|
||||
extern int Stm32HwDacInit(void);
|
||||
extern int Stm32HwUsbInit(void);
|
||||
#ifdef BSP_USING_LWIP
|
||||
extern int ETH_BSP_Config();
|
||||
#endif
|
||||
@@ -139,6 +140,11 @@ struct InitSequenceDesc _board_init[] =
|
||||
#ifdef BSP_USING_SDIO
|
||||
{"hw sdcard init", HwSdioInit},
|
||||
#endif
|
||||
#ifdef BSP_USING_USB
|
||||
#ifdef BSP_USING_STM32_USBH
|
||||
{ "hw usb", Stm32HwUsbInit },
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BSP_USING_ADC
|
||||
{"hw adc init", Stm32HwAdcInit},
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user