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:
xuedongliang 2022-11-16 15:21:08 +08:00
commit afc27bce65
120 changed files with 16900 additions and 162 deletions

View File

@ -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.
*/

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 '/'");

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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"

View File

@ -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()

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
******************************************************************************/

View File

@ -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

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_sdio.c hardware_sdio.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_RESOURCES_SPI_LORA),y)
SRC_DIR := sx12xx
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_DIR := src
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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

View File

@ -0,0 +1,3 @@
SRC_DIR := radio
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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

View File

@ -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__

View File

@ -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;
}

View File

@ -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__

View File

@ -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

View File

@ -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, &regPaConfigInitVal );
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

View File

@ -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__

View File

@ -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__

View File

@ -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, &regValue);
// 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, &regValue);
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,&regValue);
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

View File

@ -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)(寄存器地址0x060x07,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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
SRC_DIR := hc32_usb_driver
SRC_FILES := connect_usb.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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;
}

View File

@ -0,0 +1,5 @@
SRC_FILES := usb_host_user.c usb_bsp.c
SRC_DIR := usb_host_lib
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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)
******************************************************************************/

View File

@ -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)
{
}

View File

@ -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)
******************************************************************************/

View File

@ -0,0 +1,3 @@
SRC_DIR := host_class host_core
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_DIR := msc
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
*****************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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)
******************************************************************************/

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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