更新硬件SDK

This commit is contained in:
kerwincui
2023-03-04 03:44:56 +08:00
parent dcdf6e1b7c
commit e39d3d2f03
1900 changed files with 663153 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
#ifndef BSP_CODECDRV_H
#define BSP_CODECDRV_H
#include "i2s.h"
typedef enum
{
ES8388, ///< Codec ES8388
NAU88C22, ///< Codec NAU88C22
ES7148, ///< Codec ES7148
ES7149, ///< Codec ES7149
ES8311, ///< Codec ES8311
}codecType_e;
typedef struct
{
uint8_t regAddr; ///< Register addr
uint16_t regVal; ///< Register value
}i2sI2cCfg_t;
/**
\brief Write value to codec via I2C.
\param[in] codecType The codec type you use.
\param[in] regAddr I2C register addr.
\param[in] regVal I2C register value that need to write.
\return
*/
void codecWriteVal(codecType_e codecType, uint8_t regAddr, uint16_t regVal);
uint8_t codecReadVal(codecType_e codecType, uint8_t regAddr);
//void codecCtrlVolume(codecType_e codecType, bool raise, uint8_t step);
#endif

View File

@@ -0,0 +1,77 @@
#ifndef BSP_H
#define BSP_H
#ifdef __cplusplus
extern "C" {
#endif
#include "version.h"
#include "Driver_Common.h"
#include "Driver_I2C.h"
#include "Driver_SPI.h"
#include "Driver_USART.h"
#include "RTE_Device.h"
#include "pad.h"
#include "gpio.h"
#include "ic.h"
#include "dma.h"
#include "clock.h"
#define STRING_EOL "\r\n"
#define BOARD_NAME "EC618_EVK"
#define SDK_VERSION "EC618_SW_V"SDK_MAJOR_VERSION"."SDK_MINOR_VERSION"."SDK_PATCH_VERSION
#define EVB_VERSION "EC618_HW_V"EVB_MAJOR_VERSION"."EVB_MINOR_VERSION
#define VERSION_INFO "-- SDK Version: "SDK_VERSION" -- "STRING_EOL"-- EVB Version: "EVB_VERSION" -- "STRING_EOL
#define BSP_HEADER STRING_EOL"-- Board: "BOARD_NAME " -- "STRING_EOL \
VERSION_INFO \
"-- Compiled: "__DATE__" "__TIME__" -- "STRING_EOL
#define ATI_VERSION_INFO STRING_EOL"-- Board: "BOARD_NAME " -- "STRING_EOL \
"-- SDK Version: "SDK_VERSION" -- "STRING_EOL
#define SOFTVERSION "V"SDK_MAJOR_VERSION"."SDK_MINOR_VERSION"."SDK_PATCH_VERSION
#define CREATE_SYMBOL(name, port) name##port
/** @brief UART port index
* | UART port | Hardware Flow Control |
* |-----------|-----------------------|
* | UART0 | Y |
* | UART1 | Y |
* | UART2 | N |
*/
typedef enum usart_port
{
PORT_USART_0, /**< USART port 0. */
PORT_USART_1, /**< USART port 1. */
PORT_USART_2, /**< USART port 2. */
PORT_USART_MAX, /**< The total number of USART ports (invalid UART port number). */
PORT_USART_INVALID /**< USART invalid. */
} usart_port_t;
extern ARM_DRIVER_USART *UsartPrintHandle;
extern ARM_DRIVER_USART *UsartUnilogHandle;
extern ARM_DRIVER_USART *UsartAtCmdHandle;
/** @brief IRQ Callback functions
*/
typedef void (*IRQ_Callback_t)();
uint8_t* getBuildInfo(void);
uint8_t* getATIVersionInfo(void);
uint8_t* getVersionInfo(void);
void FlushUnilogOutput(void);
void SetUnilogUart(usart_port_t port, uint32_t baudrate, bool startRecv);
void BSP_CommonInit(void);
void setOSState(uint8_t state);
uint8_t * getDebugDVersion(void);
void delay_us(uint32_t us);
#ifdef __cplusplus
}
#endif
#endif /* BSP_H */

View File

@@ -0,0 +1,9 @@
#ifndef BF30A2_H
#define BF30A2_H
#define BF30A2_I2C_ADDR 0x6e
uint16_t bf30a2GetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,170 @@
#ifndef __CAMERA_DRV_H__
#define __CAMERA_DRV_H__
#include "cspi.h"
#include "sp0A39.h"
#include "sp0821.h"
#include "gc6123.h"
#include "gc032A.h"
#include "bf30a2.h"
#include "gc6153.h"
#ifdef __USER_CODE__
#ifndef CAM_CHAIN_COUNT
#define CAMERA_ENABLE_BF30A2 1
#define BF30A2_1SDR 1
#define CAM_CHAIN_COUNT CAM_8W
#endif
#endif
/**
\addtogroup cam_interface_gr
\{
*/
typedef struct
{
uint8_t regAddr; ///< Sensor I2C register address
uint8_t regVal; ///< Sensor I2C register value
}camI2cCfg_t;
typedef enum
{
LSB_MODE = 0, ///< Little endian
MSB_MODE = 1, ///< Big endian
}endianMode_e;
typedef enum
{
WIRE_1 = 0, ///< 1 wire
WIRE_2 = 1, ///< 2 wire
}wireNum_e;
typedef enum
{
SEQ_0 = 0, ///< rxd[0] 6 4 2 0
///< rxd[1] 7 5 3 1
SEQ_1 = 1, ///< rxd[1] 6 4 2 0
///< rxd[0] 7 5 3 1
}rxSeq_e;
typedef enum
{
CSPI_0 = 0,
CSPI_1 = 1,
}cspiInstance_e;
typedef enum
{
CSPI_START = 1, ///< cspi enable
CSPI_STOP = 0, ///< Cspi disable
}cspiStartStop_e;
typedef enum
{
CSPI_INT_ENABLE = 1, ///< cspi interrupt enable
CSPI_INT_DISABLE = 0, ///< Cspi interrupt disable
}cspiIntEnable_e;
typedef struct
{
endianMode_e endianMode; ///< Endian mode
wireNum_e wireNum; ///< Wire numbers
rxSeq_e rxSeq; ///< Bit sequence in 2 wire mode
uint8_t cpol;
uint8_t cpha;
uint8_t yOnly;
uint8_t rowScaleRatio;
uint8_t colScaleRatio;
uint8_t scaleBytes;
}camParamCfg_t;
typedef void (*camCbEvent_fn) (uint32_t event); ///< Camera callback event.
typedef void (*camIrq_fn)(void); ///< Camera irq
/**
\brief Init camera, include pinMux, and enable clock.
\param[in] dataAddr Mem addr to store picture.
\param[in] cb Indicate that a picture has been taken.
\return
*/
void camInit(void* dataAddr, camCbEvent_fn cb);
/**
\brief Receive the picture has been taken.
\param[out] dataIn The buffer which is used to store the picture.
\return
*/
void camRecv(uint8_t * dataIn);
/**
\brief Init sensor's registers.
\return
*/
void camRegCfg(void);
/**
\brief Write some parameters into the sensor.
\param[in] regInfo Sensor I2C addr and value.
\return
*/
void camWriteReg(camI2cCfg_t* regInfo);
/**
\brief Read from the sensor's I2C address.
\param[in] regAddr Sensor's I2C register address.
\return
*/
uint8_t camReadReg(uint8_t regAddr);
/**
\brief Start or stop Camera controller.
\param[in] startStop If true, start camera controller. If false, stop camera controller.
\return
*/
void camStartStop(cspiStartStop_e startStop);
/**
\brief Register irq for cspi.
\param[in] instance cspi0 or cspi1.
\param[in] irqCb irq cb.
\return
*/
void camRegisterIRQ(cspiInstance_e instance, camIrq_fn irqCb);
/**
\brief Get cspi status.
\param[in] instance cspi0 or cspi1.
\return
*/
uint32_t camGetCspiStats(cspiInstance_e instance);
/**
\brief Clear cspi interrupt status.
\param[in] instance cspi0 or cspi1.
\param[in] mask which bit needs to clear.
\return
*/
void camClearIntStats(cspiInstance_e instance, uint32_t mask);
/**
\brief Set memory addr which is used to store picture of camera.
\param[in] dataAddr data addr.
\return
*/
void camSetMemAddr(uint32_t dataAddr);
/**
\brief Enable or disable interrupt of cspi.
\param[in] intEnable interrupt enable or not.
\return
*/
void cspiIntEnable(cspiIntEnable_e intEnable);
/** \} */
#endif

View File

@@ -0,0 +1,9 @@
#ifndef GC032A_H
#define GC032A_H
#define GC032A_I2C_ADDR 0x21
uint16_t gc032aGetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef GC6123_H
#define GC6123_H
#define GC6123_I2C_ADDR 0x40
uint16_t gc6123GetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef GC6153_H
#define GC6153_H
#define GC6153_I2C_ADDR 0x40
uint16_t gc6153GetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,36 @@
#ifndef __I2C_GPIO_H__
#define __I2C_GPIO_H__
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
// sda pin definition. gpio16
#define SDA_GPIO_INSTANCE (1)
#define SDA_GPIO_PIN (0)
#define SDA_GPIO_ADDR (31)
#define SDA_PAD_ALT_FUNC (PAD_MUX_ALT0)
// scl pin definition. gpio17
#define SCL_GPIO_INSTANCE (1)
#define SCL_GPIO_PIN (1)
#define SCL_GPIO_ADDR (32)
#define SCL_PAD_ALT_FUNC (PAD_MUX_ALT0)
#define I2C_SDA_0 do {GPIO_pinWrite(SDA_GPIO_INSTANCE, 1 << SDA_GPIO_PIN, 0);}while(0)
#define I2C_SDA_1 do {GPIO_pinWrite(SDA_GPIO_INSTANCE, 1 << SDA_GPIO_PIN, 1 << SDA_GPIO_PIN);}while(0)
#define I2C_SCL_0 do {GPIO_pinWrite(SCL_GPIO_INSTANCE, 1 << SCL_GPIO_PIN, 0);}while(0)
#define I2C_SCL_1 do {GPIO_pinWrite(SCL_GPIO_INSTANCE, 1 << SCL_GPIO_PIN, 1 << SCL_GPIO_PIN);}while(0)
void i2cGpioInit();
uint8_t i2cReadByte();
void i2cWritebyte(uint8_t byte);
void i2cStop();
void i2cStart();
void i2cAck();
#endif

View File

@@ -0,0 +1,9 @@
#ifndef SP0821_H
#define SP0821_H
#define SP0821_I2C_ADDR 0x43
uint16_t sp0821GetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,9 @@
#ifndef SP0A39_H
#define SP0A39_H
#define SP0A39_I2C_ADDR 0x21
uint16_t sp0a39GetRegCnt(char* regName);
#endif

View File

@@ -0,0 +1,96 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: eepRom.h
* Description: EC618 eepRom driver file
* History: Rev1.0 2020-12-17
*
****************************************************************************/
#ifndef _EEPROM_EC618_H
#define _EEPROM_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
#include "oneWire.h"
/**
\addtogroup eepRom_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/** \brief ROM Operation Command */
#define ROM_READ_CMD 0x33
#define ROM_MATCH_CMD 0x55
#define ROM_SKIP_CMD 0xCC
#define ROM_SEARCH_CMD 0xF0
/** \brief Memory Operation Command */
#define MEM_READ_CMD 0xF0
#define SCRATCHPAD_READ_CMD 0xAA
#define SCRATCHPAD_WRITE_CMD 0x0F
#define SCRATCHPAD_COPY_CMD 0x55
/** \brief EEPROM Status */
#define EEPROMDRV_OK (0)
#define EEPROMDRV_RESET_ERR (-1)
#define EEPROMDRV_RESETPD_ERR (-2)
#define EEPROMDRV_ROMREAD_ERR (-3)
#define EEPROMDRV_ROMMATCH_ERR (-4)
#define EEPROMDRV_ROMSKIP_ERR (-5)
#define EEPROMDRV_ROMSEARCH_ERR (-6)
#define EEPROMDRV_MEMREAD_ERR (-7)
#define EEPROMDRV_SCRATCHPADREAD_ERR (-8)
#define EEPROMDRV_SCRATCHPADWRITE_ERR (-9)
#define EEPROMDRV_SCRATCHPADCOPY_ERR (-10)
/**
\fn int32_t eePromReadRom(uint8_t* romCode)
\brief EEPROM read ROM code
\param[out] romCode ROM infomation read back.
\return read ROM status
*/
int32_t eePromReadRom(uint8_t* romCode);
/**
\fn eePromReadMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer)
\brief EEPROM read memory.
\param[in] targetAddr The target address of EEPROM.
\param[in] len Length of this read.
\param[out] buffer Data read back.
\return read memory status
*/
int32_t eePromReadMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer);
/**
\fn int32_t eePromWriteMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer)
\brief EEPROM write memory
\param[in] targetAddr The target address of EEPROM.
\param[in] len Length of this write.
\param[in] buffer Data needs to write into memory.
\return Write memory status
*/
int32_t eePromWriteMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer);
void eepRomInit(OwModeSel_e mode);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,70 @@
#include "stdint.h"
#include "bsp.h"
#define SPI_INSTANCE SPI0
#define SPI_APB_CLOCK PCLK_SPI0
#define SPI_FUNC_CLOCK FCLK_SPI0
#define SPI_DMA_TX_REQID DMA_REQUEST_SPI0_TX // DMA SPI Request ID
#define LCD_DMA_DESCRIPTOR_CHAIN_NUM 20 // 30w pixel
#define LCD_TRANSFER_SIZE_ONCE 480//7680 // less than 8k
#define HEIGHT (129)
#define WIDTH (128)
#define SPI_BUS_SPEED (1000000) // 13M
#define SPI_FLAG_TIMEOUT (0x1000)
// SPI cs pin definition
#define CS_GPIO_INSTANCE (0)
#define CS_GPIO_PIN (8)
#define CS_GPIO_ADDR (23)
#define CS_PAD_ALT_FUNC (PAD_MUX_ALT0)
// SPI clk pin definition
#define CLK_GPIO_INSTANCE (0)
#define CLK_GPIO_PIN (11)
#define CLK_GPIO_ADDR (26)
#define CLK_PAD_ALT_FUNC (PAD_MUX_ALT1)
// SPI mosi pin definition
#define MOSI_GPIO_INSTANCE (0)
#define MOSI_GPIO_PIN (9)
#define MOSI_GPIO_ADDR (24)
#define MOSI_PAD_ALT_FUNC (PAD_MUX_ALT1)
// SPI miso pin definition
#define MISO_GPIO_INSTANCE (0)
#define MISO_GPIO_PIN (10)
#define MISO_GPIO_ADDR (25)
#define MISO_PAD_ALT_FUNC (PAD_MUX_ALT1)
// LCD rst pin definition
#define RST_GPIO_INSTANCE (1)
#define RST_GPIO_PIN (4)
#define RST_GPIO_ADDR (40)
#define RST_PAD_ALT_FUNC (PAD_MUX_ALT0)
// LCD ds pin definition
#define DS_GPIO_INSTANCE (1)
#define DS_GPIO_PIN (12)
#define DS_GPIO_ADDR (48)
#define DS_PAD_ALT_FUNC (PAD_MUX_ALT0)
// LCD en pin definition
#define EN_GPIO_INSTANCE (1)
#define EN_GPIO_PIN (5)
#define EN_GPIO_ADDR (41)
#define EN_PAD_ALT_FUNC (PAD_MUX_ALT0)
void st7571_init(void);
void displayPic_60x80(uint8_t *p);
void st7571CleanScreen(void);

View File

@@ -0,0 +1,68 @@
#include "stdint.h"
#include "bsp.h"
#define SPI_INSTANCE SPI0
#define SPI_APB_CLOCK PCLK_SPI0
#define SPI_FUNC_CLOCK FCLK_SPI0
#define SPI_DMA_TX_REQID DMA_REQUEST_SPI0_TX // DMA SPI Request ID
#define LCD_DMA_DESCRIPTOR_CHAIN_NUM 20 // 30w pixel
#define LCD_TRANSFER_SIZE_ONCE 480//7680 // less than 8k
#define SPI_BUS_SPEED (1000000) // 13M
#define SPI_FLAG_TIMEOUT (0x1000)
#define HEIGHT (320)
#define WIDTH (240)
#define RED (0xf800)
#define GREEN (0x07e0)
#define BLUE (0x001f)
#define YELLOW (0xffe0)
#define WHITE (0xffff)
#define BLACK (0x0000)
#define PURPLE (0xf81f)
// SPI cs pin definition
#define CS_GPIO_INSTANCE (0)
#define CS_GPIO_PIN (8)
#define CS_GPIO_ADDR (23)
#define CS_PAD_ALT_FUNC (PAD_MUX_ALT0)
// SPI clk pin definition
#define CLK_GPIO_INSTANCE (0)
#define CLK_GPIO_PIN (11)
#define CLK_GPIO_ADDR (26)
#define CLK_PAD_ALT_FUNC (PAD_MUX_ALT1)
// SPI mosi pin definition
#define MOSI_GPIO_INSTANCE (0)
#define MOSI_GPIO_PIN (9)
#define MOSI_GPIO_ADDR (24)
#define MOSI_PAD_ALT_FUNC (PAD_MUX_ALT1)
// SPI miso pin definition
#define MISO_GPIO_INSTANCE (0)
#define MISO_GPIO_PIN (10)
#define MISO_GPIO_ADDR (25)
#define MISO_PAD_ALT_FUNC (PAD_MUX_ALT1)
// LCD rst pin definition
#define RST_GPIO_INSTANCE (1)
#define RST_GPIO_PIN (1)
#define RST_GPIO_ADDR (32)
#define RST_PAD_ALT_FUNC (PAD_MUX_ALT0)
// LCD ds pin definition
#define DS_GPIO_INSTANCE (1)
#define DS_GPIO_PIN (0)
#define DS_GPIO_ADDR (31)
#define DS_PAD_ALT_FUNC (PAD_MUX_ALT0)
void st7789v2_init(void);

View File

@@ -0,0 +1,85 @@
#ifndef IMAGE_PROCESS_H
#define IMAGE_PROCESS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
#include <stdlib.h>
/**
\brief Convert yuv422 to rgb565, used in color screen.
\param[in] inbuf source memory.
\param[out] outbuf output memory.
\param[in] width source picture width.
\param[in] height source picture height.
\return
*/
void yuv422ToRgb565(const void* inbuf, void* outbuf, int width, int height);
/**
\brief Scale the picture. Now this api can only zoom out the picture.
\param[in] ratio Zoom out ratio.
\param[in] inPtr Data source.
\param[in] width Source data width.
\param[in] height Source data height.
\param[out] outPtr Output data address.
\return
*/
void scalePic(uint8_t ratio, uint8_t* inPtr, uint16_t width, uint16_t height, uint8_t *outPtr);
/**
\brief Clockwise rotate 90 degree.
\param[in,out] mem Data source.
\param[in] width Source picture width.
\param[in] height Source picture height.
\return
*/
void imageRotate(uint8_t* mem, uint32_t width, uint32_t height);
/**
\brief Organize the bytes as horizontal or vertical.
\param[in] inPut Src data.
\param[in] pageLen The pageNum you want for these data, this param is set by you.
\param[in] width The width you want for these data, this param is set by you.
\param[out] outPut Output buffer.
\param[in] horizotal These data you want to array them as horizontal or vertical.
\return
*/
void storeByteIntoArray(uint8_t *inPut, uint8_t pageLen, uint16_t width, uint8_t *outPut, bool horizotal);
/**
\brief Merge 8bytes into one byte, used in 1-bit LCD.
\param[in] p Src data.
\param[out] outPut Output buffer.
\param[in] width Source data width.
\param[out] height Source data height.
\param[in] horizotal Fetch the data by row or by column.
\param[in] inByteRevert Within the byte, positive or reverse the bit sequence.
\return index How many bytes has been returned, for debug use
*/
uint16_t merge8Bytes2OneByte(uint8_t* p, uint8_t *outPut, uint16_t width, uint16_t height, bool horizotal, bool inByteRevert);
/**
\brief Binary the source picture.
\param[in] inPut Src data.
\param[in] width Source picture width.
\param[in] height Source picture height.
\param[out] outPut Output buffer.
\return
*/
void calBinary(uint8_t* inPut, uint16_t width, uint16_t height, uint8_t* outPut);
#ifdef __cplusplus
}
#endif
#endif /* IMAGE_PROCESS_H */

View File

@@ -0,0 +1,114 @@
#ifndef BSP_LCD_H
#define BSP_LCD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
// Only need to choose which LCD you use
#define ST7789V2_ENABLE 0
#define ST7571_ENABLE 1
#if (ST7789V2_ENABLE)
#include "st7789v2.h"
#endif
#if (ST7571_ENABLE)
#include "st7571.h"
#endif
#define SPI SPI_INSTANCE
#define SPI_CS_LOW do {GPIO_pinWrite(SPI_CS_GPIO_INSTANCE, 1 << SPI_CS_GPIO_PIN, 0);}while(0)
#define SPI_CS_HIGH do {GPIO_pinWrite(SPI_CS_GPIO_INSTANCE, 1 << SPI_CS_GPIO_PIN, 1 << SPI_CS_GPIO_PIN);}while(0)
#define LCD_DS_LOW do {GPIO_pinWrite(LCD_DS_GPIO_INSTANCE, 1 << LCD_DS_GPIO_PIN, 0);}while(0)
#define LCD_DS_HIGH do {GPIO_pinWrite(LCD_DS_GPIO_INSTANCE, 1 << LCD_DS_GPIO_PIN, 1 << LCD_DS_GPIO_PIN);}while(0)
#define LCD_RST_LOW do {GPIO_pinWrite(LCD_RST_GPIO_INSTANCE, 1 << LCD_RST_GPIO_PIN, 0);}while(0)
#define LCD_RST_HIGH do {GPIO_pinWrite(LCD_RST_GPIO_INSTANCE, 1 << LCD_RST_GPIO_PIN, 1 << LCD_RST_GPIO_PIN);}while(0)
#define SPI_SEND_DATA(data) do {SPI->DR = data;}while(0)
#define SPI_READ_DATA (SPI->DR)
#define SPI_WAIT_TX_DONE do {}while(!((SPI->SR & (SPI_SR_BSY_Msk | SPI_SR_TFE_Msk)) == SPI_SR_TFE_Msk))
#define SPI_IS_BUSY do {}while((SPI->SR & SPI_SR_BSY_Msk) == SPI_SR_BSY_Msk)
#define SPI_START_DMA_CHANNEL(channel) do {*((uint32_t*)(0x4d1f0000 + (channel << 2))) |= 0x80000000;}while(0)
#define SPI_STOP_DMA_CHANNEL(channel) do {*((uint32_t*)(0x4d1f0000 + (channel << 2))) &= ~0x80000000;}while(0)
#define SPI_ENABLE_TX_DMA do {SPI->DMACR |= SPI_DMACR_TXDMAE_Msk;}while(0)
// Spi cs pin
#define SPI_CS_GPIO_INSTANCE (CS_GPIO_INSTANCE)
#define SPI_CS_GPIO_PIN (CS_GPIO_PIN)
#define SPI_CS_PAD_ADDR (CS_GPIO_ADDR)
#define SPI_CS_PAD_ALT_FUNC (CS_PAD_ALT_FUNC)
// Spi clk pin
#define SPI_CLK_GPIO_INSTANCE (CLK_GPIO_INSTANCE)
#define SPI_CLK_GPIO_PIN (CLK_GPIO_PIN)
#define SPI_CLK_PAD_ADDR (CLK_GPIO_ADDR)
#define SPI_CLK_PAD_ALT_FUNC (CLK_PAD_ALT_FUNC)
// Spi mosi pin
#define SPI_MOSI_GPIO_INSTANCE (MOSI_GPIO_INSTANCE)
#define SPI_MOSI_GPIO_PIN (MOSI_GPIO_PIN)
#define SPI_MOSI_PAD_ADDR (MOSI_GPIO_ADDR)
#define SPI_MOSI_PAD_ALT_FUNC (MOSI_PAD_ALT_FUNC)
// Spi miso pin
#define SPI_MISO_GPIO_INSTANCE (MISO_GPIO_INSTANCE)
#define SPI_MISO_GPIO_PIN (MISO_GPIO_PIN)
#define SPI_MISO_PAD_ADDR (MISO_GPIO_ADDR)
#define SPI_MISO_PAD_ALT_FUNC (MISO_PAD_ALT_FUNC)
// Lcd rst pin
#define LCD_RST_GPIO_INSTANCE (RST_GPIO_INSTANCE)
#define LCD_RST_GPIO_PIN (RST_GPIO_PIN)
#define LCD_RST_PAD_ADDR (RST_GPIO_ADDR)
#define LCD_RST_PAD_ALT_FUNC (RST_PAD_ALT_FUNC)
// Lcd ds pin
#define LCD_DS_GPIO_INSTANCE (DS_GPIO_INSTANCE)
#define LCD_DS_GPIO_PIN (DS_GPIO_PIN)
#define LCD_DS_PAD_ADDR (DS_GPIO_ADDR)
#define LCD_DS_PAD_ALT_FUNC (DS_PAD_ALT_FUNC)
#if (ST7571_ENABLE)
// Lcd en pin
#define LCD_EN_GPIO_INSTANCE (EN_GPIO_INSTANCE)
#define LCD_EN_GPIO_PIN (EN_GPIO_PIN)
#define LCD_EN_PAD_ADDR (EN_GPIO_ADDR)
#define LCD_EN_PAD_ALT_FUNC (EN_PAD_ALT_FUNC)
#endif
typedef void (*pTxCb)(uint32_t event);
uint8_t lcdReadData(void);
void lcdReadId(void);
void lcdWriteCmd(uint8_t cmd);
void lcdWriteData(uint8_t data);
void lcdInit(pTxCb txCb);
void mDelay(uint32_t mDelay);
//void lcdWriteData16(uint16_t data);
//void lcdDispColor(uint16_t color);
void lcdDispWindows(void);
//void lcdWriteDataDma(uint16_t color);
void lcdWriteSetup(uint8_t * dataBuf, uint16_t dataCnt);
void lcdWriteCtrl(bool startOrStop);
void lcdClearScreen();
void lcdDispPic(uint8_t * pic);
#ifdef __cplusplus
}
#endif
#endif /* BSP_LCD_H */

View File

@@ -0,0 +1,40 @@
#ifndef _NTC_H
#define _NTC_H
#ifdef __cplusplus
extern "C" {
#endif
/**
\brief Get NTC temperature
Vref(AIO1 output 1200000 uV)
v
|
|
+-+
| |
| | R = 10 Kohm
| |
+-+
|--------->(AIO2)
+-+
| |
| | Rntc
| |
+-+
|
-----
--- (GND)
-
\param[in] adcInputVoltage ADC input voltage in unit of uV
\return temperature in unit of mili degree centigrade
*/
int32_t ntcGetTemperature(int32_t adcInputVoltage);
#ifdef __cplusplus
}
#endif
#endif /* _NTC_H */

View File

@@ -0,0 +1,506 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: plat_config.h
* Description: platform configuration header file
* History: Rev1.0 2019-01-18
* Rev1.1 2019-11-27 Reimplement file operations with OSA APIs(LFS wrapper), not directly using LFS APIs in case of file system replacement
* Rev1.2 2020-01-01 Separate plat config into two parts, FS and raw flash
*
****************************************************************************/
#ifndef _PLAT_CONFIG_H
#define _PLAT_CONFIG_H
#include "Driver_Common.h"
#include "cmsis_compiler.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define FS_PLAT_CONFIG_FILE_CURRENT_VERSION (0)
#define RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION (1)
/** \brief config file header typedef */
__PACKED_STRUCT _config_file_header
{
uint16_t fileBodySize; /**< size of file body, in unit of byte */
uint8_t version; /**< file version, this field shall be updated when file structure is changed */
uint8_t checkSum; /**< check sum value of file body */
};
typedef struct _config_file_header config_file_header_t;
/** \brief typedef of platform configuration stored in fs */
typedef __PACKED_UNION _EPAT_atPortFrameFormat
{
uint32_t wholeValue;
__PACKED_STRUCT _config
{
uint32_t dataBits : 3;
uint32_t parity : 2;
uint32_t stopBits : 2;
uint32_t flowControl : 3;
} config;
} atPortFrameFormat_t;
// ulg port enum
typedef enum
{
PLAT_CFG_ULG_PORT_USB=0,
PLAT_CFG_ULG_PORT_UART,
PLAT_CFG_ULG_PORT_MIX,
PLAT_CFG_ULG_PORT_MAX
} PlatCfgUlgPort_e;
/** \brief typedef of platform configuration stored in fs */
typedef __PACKED_STRUCT _NVM_EPAT_plat_config
{
/** PM on/off flag
* valid value:
* 0x504D5544 -- PM is disabled, "PMUD"
* 0x504D5545 -- PM is enabled, "PMUE"
*/
uint32_t enablePM;
/** sleep mode
* valid value:
* 0 -- dummy
* 1 -- dummy
*/
uint8_t sleepMode;
/** wait n ms before sleep, when wakeup from pad
* valid value:
* 0 -- do not wait
* x -- wait x ms
*/
uint32_t slpWaitTime;
/** AT baudrate,for AP only
* should be equal to 'atPortBaudRate' in struct plat_config_raw_flash_t
*/
uint32_t atPortBaudRate;
/** AT port frame format*/
atPortFrameFormat_t atPortFrameFormat;
/** ECQSCLK config
* valid value:
* 0 -- ECQSCLK set to 0
* 1 -- ECQSCLK set to 1
*/
uint8_t ecSclkCfg;
} plat_config_fs_t;
/** \brief typedef of platform configuration stored in raw flash --old v0*/
__PACKED_STRUCT _plat_config_raw_flash_v0
{
/** action to perform when assert or hard fault occurs
* valid value:
* 0 -- dump full exception info to flash and EPAT tool then trapped in endless loop(while(1))
* 1 -- print necessary exception info then reset
* 2 -- dump full exception info to flash then reset
* 3 -- dump full exception info to flash and EPAT tool then reset
* 4 -- reset directly
* 10 -- enable uart help dump and dump full exception info to flash and EPAT tool then trapped in endless loop(while(1))
* 13 -- enable uart help dump and dump full exception info to flash and EPAT tool, and then reset
*/
uint8_t faultAction;
/** port select for dump info output when exception occurs
* valid value:
* 0,1,2,3,(4) -- specify which port
* 0xff -- disable this function
*/
uint8_t uartDumpPort;
/** WDT start/stop control
* valid value:
* 0 -- stop WDT
* 1 -- start WDT
*/
uint8_t startWDT;
/** unilog on/off flag
* valid value:
* 0 -- unilog is disabled
* 1 -- only sw log is enabled
* 2 -- All log is enabled
*/
uint8_t logControl;
/** uart baudrate for unilog output */
uint32_t uartBaudRate;
/** debug trace log level setting, refer to 'DebugTraceLevelType_e' */
uint32_t logLevel;
/** unilog output port select
* valid value:
* 0 -- USB
* 1 -- UART
* 2 -- MIX(for future use UART/USB dynamic select)
**/
PlatCfgUlgPort_e logPortSel;
/** RNDIS enum control
* valid value:
* 0 -- enable USB init and enum RNDIS
* 1 -- enable USB init but not enum RNDIS
* 2 -- disable USB init
*/
uint8_t usbCtrl;
/** usb software trace control
* valid value:
* 0 -- disable all usb software trace
* 1 -- enable all usb software trace
* others -- misc usb software trace
*/
uint8_t usbSwTrace;
/** USB sleep mask
* valid value:
* 0 -- usb should vote to enter sleep
* 1 -- do not consider usb vote before sleep
*/
uint8_t usbSlpMask;
/** USB sleep thd
* valid value:
* set the minimal time to sleep, when usbSlpMask=1
*/
uint16_t usbSlpThd;
/** pwrkey mode
* valid value:
* 1 power key mode
* 0 normal key mode
*/
uint8_t pwrKeyMode;
};
// fota urc port type
typedef enum
{
PLAT_CFG_FOTA_URC_PORT_USB=0,
PLAT_CFG_FOTA_URC_PORT_UART,
PLAT_CFG_FOTA_URC_PORT_MAXTYPE
} PlatCfgFotaUrcPortType_e;
#define PLAT_CFG_FOTA_URC_USB_PORT_IDX_MIN 0
#define PLAT_CFG_FOTA_URC_USB_PORT_IDX_MAX 2
#define PLAT_CFG_FOTA_URC_UART_PORT_IDX_MIN 0
#define PLAT_CFG_FOTA_URC_UART_PORT_IDX_MAX 1
#define PLAT_CFG_RAW_FLASH_RSVD_SIZE 21
/** \brief typedef of platform configuration stored in raw flash */
__PACKED_STRUCT _plat_config_raw_flash
{
/** action to perform when assert or hard fault occurs
* valid value:
* 0 -- dump full exception info to flash and EPAT tool then trapped in endless loop(while(1))
* 1 -- print necessary exception info then reset
* 2 -- dump full exception info to flash then reset
* 3 -- dump full exception info to flash and EPAT tool then reset
* 4 -- reset directly
* 10 -- enable uart help dump and dump full exception info to flash and EPAT tool then trapped in endless loop(while(1))
* 13 -- enable uart help dump and dump full exception info to flash and EPAT tool, and then reset
*/
uint8_t faultAction;
/** port select for dump info output when exception occurs
* valid value:
* 0,1,2,3,(4) -- specify which port
* 0xff -- disable this function
*/
uint8_t uartDumpPort;
/** WDT start/stop control
* valid value:
* 0 -- stop WDT
* 1 -- start WDT
*/
uint8_t startWDT;
/** unilog on/off flag
* valid value:
* 0 -- unilog is disabled
* 1 -- only sw log is enabled
* 2 -- All log is enabled
*/
uint8_t logControl;
/** uart baudrate for unilog output */
uint32_t uartBaudRate;
/** debug trace log level setting, refer to 'DebugTraceLevelType_e' */
uint32_t logLevel;
/** unilog output port select
* valid value:
* 0 -- USB
* 1 -- UART
* 2 -- MIX(for future use UART/USB dynamic select)
**/
PlatCfgUlgPort_e logPortSel;
/** RNDIS enum control
* valid value:
* 0 -- enable USB init and enum RNDIS
* 1 -- enable USB init but not enum RNDIS
* 2 -- disable USB init
*/
uint8_t usbCtrl;
/** usb software trace control
* valid value:
* 0 -- disable all usb software trace
* 1 -- enable all usb software trace
* others -- misc usb software trace
*/
uint8_t usbSwTrace;
/** USB sleep mask
* valid value:
* 0 -- usb should vote to enter sleep
* 1 -- do not consider usb vote before sleep
*/
uint8_t usbSlpMask;
/** USB sleep thd
* valid value:
* set the minimal time to sleep, when usbSlpMask=1
*/
uint16_t usbSlpThd;
/** pwrkey mode
* valid value:
* 1 power key mode
* 0 normal key mode
*/
uint8_t pwrKeyMode;
/** USB VBUS MODE Enable,Disable Flag
* valid value:
* 0 -- usb vbus mode disable
* 1 -- usb vbus mode enable
*/
uint8_t usbVBUSModeEn;
/** USB VBUS MODE Wakup Pad Index
* valid value:
* 0,1,2,3,4,5 PAD IDX FOR USB VBUS WKUP PAD
*/
uint8_t usbVBUSWkupPad;
/** USB NET IF SEL
* valid value:
* 0----RNDIS,default
* 1----ECM
*/
uint8_t usbNet;
/** USB VCOM EN bitmap
* valid value:
* bit0---vcom0
* bit1---vcom1
* ----
* ----
*/
uint8_t usbVcomEnBitMap;
/** AT/fotaURC baudrate, for AP & BL*/
uint32_t atPortBaudRate;
/** FOTA URC output port select
* valid value(Bit4-7):
* 0 -- USB
* 1 -- UART
**
* valid value(Bit0-3):
* 0-2 -- USB
* 0-1 -- UART
**/
uint8_t fotaUrcPortSel;
/** pmuInCdrx
* valid value:
* 0----
* 1----
*/
uint8_t pmuInCdrx;
/** slpLimitEn
* valid value:
* 0---- disable
* 1---- enable
*/
uint8_t slpLimitEn;
/** slpLimitTime
* valid value:
* 0---0xFFFFFFFF
*/
uint32_t slpLimitTime;
/* 'PLAT_CFG_RAW_FLASH_RSVD_SIZE' bytes rsvd for future */
uint8_t resv[PLAT_CFG_RAW_FLASH_RSVD_SIZE];
};
typedef struct _plat_config_raw_flash plat_config_raw_flash_t;//current
typedef struct _plat_config_raw_flash_v0 plat_config_raw_flash_v0_t;//old v0
/** \brief typedef of platform info layout stored in raw flash */
__PACKED_STRUCT _plat_info_layout
{
config_file_header_t header; /**< raw flash plat config header */
plat_config_raw_flash_t config; /**< raw flash plat config body */
uint32_t fsAssertCount; /**< count for monitoring FS assert, when it reaches specific number, FS region will be re-formated */
};
typedef struct _plat_info_layout plat_info_layout_t;
/** @brief List of platform configuration items used to set/get sepecific setting */
typedef enum _plat_config_id
{
PLAT_CONFIG_ITEM_FAULT_ACTION = 0, /**< faultAction item */
PLAT_CONFIG_ITEM_UART_DUMP_PORT, /**< uartDumpPort item */
PLAT_CONFIG_ITEM_START_WDT, /**< startWDT item */
PLAT_CONFIG_ITEM_LOG_CONTROL, /**< logControl item */
PLAT_CONFIG_ITEM_LOG_BAUDRATE, /**< uart baudrate for log output */
PLAT_CONFIG_ITEM_LOG_LEVEL, /**< logLevel item */
PLAT_CONFIG_ITEM_ENABLE_PM, /**< enablePM item */
PLAT_CONFIG_ITEM_SLEEP_MODE, /**< sleepMode item */
PLAT_CONFIG_ITEM_WAIT_SLEEP, /**< wait ms before sleep */
PLAT_CONFIG_ITEM_AT_PORT_BAUDRATE, /**< AT port baudrate */
PLAT_CONFIG_ITEM_AT_PORT_FRAME_FORMAT, /**< AT port frame format */
PLAT_CONFIG_ITEM_ECSCLK_CFG, /**< ECSCLK config */
PLAT_CONFIG_ITEM_LOG_PORT_SEL, /**< ULG output port select */
PLAT_CONFIG_ITEM_USB_CTRL, /**< USB control */
PLAT_CONFIG_ITEM_USB_SW_TRACE_FLAG, /**< USB control */
PLAT_CONFIG_ITEM_USB_SLEEP_MASK, /**< USB Sleep Vote Mask */
PLAT_CONFIG_ITEM_USB_SLEEP_THD, /**< USB Sleep Thread */
PLAT_CONFIG_ITEM_PWRKEY_MODE, /**< PWRKEY Mode */
PLAT_CONFIG_ITEM_USB_VBUS_MODE_EN, /**< USB VBUS MODE ENABLE, DISABLE*/
PLAT_CONFIG_ITEM_USB_VBUS_WKUP_PAD, /**< USB VBUS MODE WKUP PAD INDEX*/
PLAT_CONFIG_ITEM_USB_NET, /**< USB NET Select*/
PLAT_CONFIG_ITEM_USB_VCOM_EN_BMP, /**< USB VCOM Enabled Bitmap*/
PLAT_CONFIG_ITEM_FOTA_URC_PORT_SEL, /**< FOTA URC Port Select*/
PLAT_CONFIG_ITEM_PMUINCDRX, /**< PMUINCDRX Select*/
PLAT_CONFIG_ITEM_SLP_LIMIT_EN, /**< enable sleep time limit*/
PLAT_CONFIG_ITEM_SLP_LIMIT_TIME, /**< set maximum sleep time in mili second*/
PLAT_CONFIG_ITEM_TOTAL_NUMBER /**< total number of items */
} plat_config_id_t;
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
\fn void BSP_SavePlatConfigToFs(void)
\brief Save platform configuration into FS
\return void
*/
void BSP_SavePlatConfigToFs(void);
/**
\fn void BSP_LoadPlatConfigFromFs(void)
\brief Load platform configuration from FS
\return void
*/
void BSP_LoadPlatConfigFromFs(void);
/**
\fn plat_config_fs_t* BSP_GetFsPlatConfig(void)
\brief Get FS platform configuration variable pointer
\return pointer to internal platform configuration loaded from FS
*/
plat_config_fs_t* BSP_GetFsPlatConfig(void);
/**
\fn void BSP_SavePlatConfigToRawFlash(void)
\brief Save platform configuration into raw flash
\return void
*/
void BSP_SavePlatConfigToRawFlash(void);
/**
\fn void BSP_LoadPlatConfigFromRawFlash(void)
\brief Load platform configuration from raw flash
\return void
*/
void BSP_LoadPlatConfigFromRawFlash(void);
/**
\fn plat_config_raw_flash_t* BSP_GetRawFlashPlatConfig(void)
\brief Get raw flash platform configuration variable pointer
\return pointer to internal platform configuration loaded from raw flash
*/
plat_config_raw_flash_t* BSP_GetRawFlashPlatConfig(void);
/**
\fn uint32_t BSP_GetPlatConfigItemValue(plat_config_id_t id)
\brief Get value of specific platform configuration item
\param[in] id id of platform configuration item, \ref plat_config_id_t
\return value of current configuration item
*/
uint32_t BSP_GetPlatConfigItemValue(plat_config_id_t id);
/**
\fn void BSP_SetPlatConfigItemValue(plat_config_id_t id, uint32_t value)
\brief Set value of specific platform configuration item
\param[in] id id of platform configuration item, \ref plat_config_id_t
\param[in] value value of configuration item to set
\return void
*/
void BSP_SetPlatConfigItemValue(plat_config_id_t id, uint32_t value);
/**
\fn uint32_t BSP_GetFSAssertCount(void)
\brief Fetch current 'fsAssertCount' value from PLAT_INFO region
\return current fsAssertCount value
*/
uint32_t BSP_GetFSAssertCount(void);
/**
\fn void BSP_SetFSAssertCount(uint32_t value);
\brief Update 'fsAssertCount' value
\param[in] value new value assigned to 'fsAssertCount'
\return void
\note Internal use only on FS assert occurs
*/
void BSP_SetFSAssertCount(uint32_t value);
/**
\fn void BSP_SetFsPorDefaultValue(void);
\brief when por happened some data may retore to it's default
\return void
*/
void BSP_SetFsPorDefaultValue(void);
#ifdef __cplusplus
}
#endif
#endif /* _PLAT_CONFIG_H */

View File

@@ -0,0 +1,172 @@
#include "codecDrv.h"
void delay_us(uint32_t us);
extern ARM_DRIVER_I2C Driver_I2C0;
static ARM_DRIVER_I2C *i2cDrvInstance = &CREATE_SYMBOL(Driver_I2C, 0);
void codecI2cInit()
{
i2cDrvInstance->Initialize(NULL);
i2cDrvInstance->PowerControl(ARM_POWER_FULL);
i2cDrvInstance->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_STANDARD);
i2cDrvInstance->Control(ARM_I2C_BUS_CLEAR, 0);
}
void codecI2cWrite(char* codecName, uint8_t slaveAddr, i2sI2cCfg_t* i2cCfg)
{
uint8_t cmd[2] = {0, 0};
uint8_t regAddr = i2cCfg->regAddr;
uint16_t regData = i2cCfg->regVal;
if (strcmp(codecName, "es8388") == 0)
{
cmd[0] = regAddr;
cmd[1] = regData & 0xff;
}
else if (strcmp(codecName, "NAU88C22") == 0)
{
cmd[0] = (regAddr << 1) | ((regData & 0x100) >> 8);
cmd[1] = regData & 0xff;
}
else if(strcmp(codecName, "es8311") == 0)
{
cmd[0] = regAddr;
cmd[1] = regData & 0xff;
}
i2cDrvInstance->MasterTransmit(slaveAddr, cmd, 2, false);
//delay_us(30 * 1000); // need to add delay in app layer which call it
}
uint8_t codecI2cRead(uint8_t slaveAddr, uint8_t regAddr)
{
uint8_t a;
a = regAddr;
uint8_t readData;
i2cDrvInstance->MasterTransmit(slaveAddr, (uint8_t *)&a, 1, true);
i2cDrvInstance->MasterReceive(slaveAddr, &readData, 1, false);
return readData;
}
uint16_t es8388GetFs(void);
uint16_t es8311GetFs(void);
uint16_t codecGetFs(codecType_e codecType)
{
switch (codecType)
{
case ES8388:
return es8388GetFs();
case NAU88C22:
return 1;
case ES7148:
return 1;
case ES7149:
return 1;
case ES8311:
return es8311GetFs();
}
return 0;
}
#if 0
/**
\fn void codecCtrlVolume(uint8_t raise, uint8_t step)
\brief Raise or decrease volume.
\param[in] codecType codec type.
\param[in] raise true means raise volume; false means decrease volume.
\param[in] step Raise or decrease vlume'samplitude everytime.
\return none.
*/
void codecCtrlVolume(codecType_e codecType, bool raise, uint8_t step)
{
i2sI2cCfg_t i2cCfg = {0,0,0};
switch (codecType)
{
case ES8388:
{
i2cCfg.regAddr = 0x1b;
raise? (i2cCfg.regVal += step) : (i2cCfg.regVal -= step);
i2cCfg.delayMs = 1;
codecI2cWrite("es8388", ES8388_IICADDR, (i2sI2cCfg_t*)&i2cCfg); // register27. Digital part
codecI2cWrite("es8388", ES8388_IICADDR, (i2sI2cCfg_t*)&i2cCfg); // register49. Analog part
return;
}
case NAU88C22:
return;
}
}
#endif
void codecWriteVal(codecType_e codecType, uint8_t regAddr, uint16_t regVal)
{
i2sI2cCfg_t i2cCfg;
i2cCfg.regAddr = regAddr;
i2cCfg.regVal = regVal;
switch (codecType)
{
case ES8388:
{
codecI2cWrite("es8388", ES8388_IICADDR, (i2sI2cCfg_t*)&i2cCfg);
return;
}
case NAU88C22:
{
codecI2cWrite("NAU88C22", NAU88C22_IICADDR, (i2sI2cCfg_t*)&i2cCfg);
return;
}
case ES7148:
{
return;
}
case ES7149:
{
return;
}
case ES8311:
{
codecI2cWrite("es8311", ES8311_IICADDR, (i2sI2cCfg_t*)&i2cCfg);
return;
}
}
}
uint8_t codecReadVal(codecType_e codecType, uint8_t regAddr)
{
uint8_t dataRead = 0x55;
switch (codecType)
{
case ES8388:
{
dataRead = codecI2cRead(ES8388_IICADDR, regAddr);
break;
}
case ES8311:
{
dataRead = codecI2cRead(ES8311_IICADDR, regAddr);
break;
}
case ES7148:
case ES7149:
case NAU88C22:
break;
}
return dataRead;
}

View File

@@ -0,0 +1,153 @@
#include "i2s.h"
#define ES8311_FS_NUM 256
i2sI2cCfg_t es8311_regInfo[] =
{
{0x45,0x00},
{0x01,0x30},
{0x02,0x10},
//Ratio=MCLK/LRCK=25612M288-48K4M096-16K; 2M048-8K
{0x02,0x00},//MCLK DIV=1
{0x03,0x10},
{0x16,0x24},
{0x04,0x20},
{0x05,0x00},
{0x06,(0<<5) + 4 -1},//(0x06,(SCLK_INV<<5) + SCLK_DIV -1);
{0x07,0x00},
{0x08,0xFF},
{0x09,(0<<7) + 0x00 + (0x00<<2)},//(0x09,(DACChannelSel<<7) + Format + (Format_Len<<2));
{0x0A,0x00 + (0x00<<2)},//(0x0A,Format + (Format_Len<<2));
{0x0B,0x00},
{0x0C,0x00},
// {0x10,(0x1C*0) + (0x60*0x01) + 0x03}, //(0x10,(0x1C*DACHPModeOn) + (0x60*VDDA_VOLTAGE) + 0x03); //VDDA_VOLTAGE=1.8V close es8311MasterInit 3.3PWR setting
{0x10,(0x1C*0) + (0x60*0x00) + 0x03}, //(0x10,(0x1C*DACHPModeOn) + (0x60*VDDA_VOLTAGE) + 0x03); //VDDA_VOLTAGE=3.3V open es8311MasterInit 3.3PWR setting
{0x11,0x7F},
{0x00,0x80 + (0<<6)},//Slave Mode (0x00,0x80 + (MSMode_MasterSelOn<<6));//Slave Mode
{0x0D,0x01},
{0x01,0x3F + (0x00<<7)},//(0x01,0x3F + (MCLK<<7));
{0x14,(0<<6) + (1<<4) + 0},//选择CH1输入+30DB GAIN (0x14,(Dmic_Selon<<6) + (ADCChannelSel<<4) + ADC_PGA_GAIN);
{0x12,0x28},
{0x13,0x00 + (0<<4)}, //(0x13,0x00 + (DACHPModeOn<<4));
{0x0E,0x02},
{0x0F,0x44},
{0x15,0x00},
{0x1B,0x0A},
{0x1C,0x6A},
{0x37,0x48},
{0x44,(0 <<7)}, //(0x44,(ADC2DAC_Sel <<7));
{0x17,210},//(0x17,ADC_Volume);
{0x32,100},//(0x32,DAC_Volume);
};
uint16_t es8311GetRegCnt(char* regName)
{
if (strcmp(regName, "es8311_master") == 0)
{
return (sizeof(es8311_regInfo) / sizeof(es8311_regInfo[0]));
}
else if (strcmp(regName, "es8311_slave") == 0)
{
return (sizeof(es8311_regInfo) / sizeof(es8311_regInfo[0]));
}
return 0;
}
void codecI2cInit(void);
void codecI2cWrite(char* codecName, uint8_t slaveAddr, i2sI2cCfg_t* i2sI2cCfg);
uint8_t codecI2cRead(uint8_t slaveAddr, uint8_t regAddr);
void es8311MasterInit()
{
uint8_t dataRead = 0xff;
codecI2cInit();
for (int i = 0; i < es8311GetRegCnt("es8311_master"); i++)
{
codecI2cWrite("es8311", ES8311_IICADDR, (i2sI2cCfg_t*)&es8311_regInfo[i]);
delay_us(10000);
}
#if 1
for (int i = 0; i < es8311GetRegCnt("es8311_master"); i++)
{
dataRead = codecI2cRead(ES8311_IICADDR, es8311_regInfo[i].regAddr);
printf("reg = 0x%02x, val = 0x%02x\n", es8311_regInfo[i].regAddr, dataRead);
}
#endif
}
void es8311SlaveInit()
{
// uint8_t dataRead = 0xff;
es8311MasterInit();
i2sI2cCfg_t i2sI2cCfg;
i2sI2cCfg.regAddr = 0x80;
i2sI2cCfg.regVal = 0<<6; // Bit7 --> 1: master(default); 0: slave
codecI2cWrite("es8311", ES8311_IICADDR, (i2sI2cCfg_t*)&i2sI2cCfg);
#if 0
for (int i = 0; i < es8311GetRegCnt("es8311_slave"); i++)
{
dataRead = codecI2cRead(ES8311_IICADDR, es8311_regInfo[i].regAddr);
printf("reg = 0x%02x, val = 0x%02x\n", es8311_regInfo[i].regAddr, dataRead);
}
#endif
}
uint16_t es8311GetFs()
{
return ES8311_FS_NUM;
}
void es8311SetMode(i2sMode_e mode)
{
uint8_t val = 0;
switch(mode)
{
case MSB_MODE:
val = 0x0F;
break;
case I2S_MODE:
val = 0x0C;
break;
case LSB_MODE:
val = 0x0D;
break;
case PCM_MODE:
val = 0x2F;
break;
}
codecWriteVal(CODEC_ES8311, 0x09, val);
}

View File

@@ -0,0 +1,146 @@
#include "i2s.h"
#define ES8388_FS_NUM 256
i2sI2cCfg_t es8388_regInfo[] =
{
{0x00,0x80},
{0x00,0x06},
{0x02,0xf3},
{0x35,0xa0},
{0x36,0x08},
{0x08,0x84}, // Bit7: 1 means master(default); 0 means slave; 0x84: master 32bit; 0x86: master 16bit
{0x0d,0x02}, // 256 ratio
{0x18,0x02}, // 256 ratio
{0x07,0x7c},
{0x2b,0x80},
{0x2d,0x10},
{0x00,0x30},
{0x01,0x00},
{0x03,0x00},
{0x06,0xff},
{0x09,0x88}, // Analog PGA: +24dB
{0x0a,0xfc},
{0x0b,0x02},
{0x0c,0x0D}, // 0x0d: 16bit Left; 0x0c: 16bit I2S; 0x0e: 16bit Right; 0x0f: 16bit PCM;
{0x10,0x00}, // digital gain ADCL
{0x11,0x00}, // digital gain ADCR
{0x12,0x05},
{0x17,0x1B}, // 0x1b: 16bit Left; 0x19: 16bit I2S; 0x1d: 16bit Right; 0x1f: 16bit PCM;
{0x19,0x76},
{0x1a,0x45}, // digital gain DACL
{0x1b,0x00}, // digital gain DACR
{0x26,0x12},
{0x2e,0x00},
{0x2f,0x00},
{0x30,0x00},
{0x31,0x00},
{0x02,0x00},
{0x00,0x37},
{0x01,0x20},
{0x27,0xb8},
{0x2a,0xb8},
{0x04,0x3c},
{0x00,0x36},
{0x19,0x72},
{0x2e,0x1e},
{0x2f,0x1e},
{0x30,0x1e},
{0x31,0x1e},
};
uint16_t es8388GetRegCnt(char* regName)
{
if (strcmp(regName, "es8388_master") == 0)
{
return (sizeof(es8388_regInfo) / sizeof(es8388_regInfo[0]));
}
else if (strcmp(regName, "es8388_slave") == 0)
{
return (sizeof(es8388_regInfo) / sizeof(es8388_regInfo[0]));
}
return 0;
}
void codecI2cInit(void);
void codecI2cWrite(char* codecName, uint8_t slaveAddr, i2sI2cCfg_t* i2sI2cCfg);
uint8_t codecI2cRead(uint8_t slaveAddr, uint8_t regAddr);
void es8388MasterInit()
{
//uint8_t dataRead = 0xff;
codecI2cInit();
for (int i = 0; i < es8388GetRegCnt("es8388_master"); i++)
{
codecI2cWrite("es8388", ES8388_IICADDR, (i2sI2cCfg_t*)&es8388_regInfo[i]);
//delay_us(10000);
}
#if 0
for (int i = 0; i < es8388GetRegCnt("es8388_master"); i++)
{
dataRead = codecI2cRead(ES8388_IICADDR, es8388_regInfo[i].regAddr);
printf("reg = 0x%02x, val = 0x%02x\n", es8388_regInfo[i].regAddr, dataRead);
}
#endif
}
void es8388SlaveInit()
{
//uint8_t dataRead = 0xff;
es8388MasterInit();
i2sI2cCfg_t i2sI2cCfg;
i2sI2cCfg.regAddr = 0x08;
i2sI2cCfg.regVal = 0<<7; // Bit7 --> 1: master(default); 0: slave
codecI2cWrite("es8388", ES8388_IICADDR, (i2sI2cCfg_t*)&i2sI2cCfg);
#if 0
for (int i = 0; i < es8388GetRegCnt("es8388_slave"); i++)
{
dataRead = codecI2cRead(ES8388_IICADDR, es8388_regInfo[i].regAddr);
printf("reg = 0x%02x, val = 0x%02x\n", es8388_regInfo[i].regAddr, dataRead);
}
#endif
}
uint16_t es8388GetFs()
{
return ES8388_FS_NUM;
}
void es8388SetMode(i2sMode_e mode)
{
uint8_t val = 0;
switch(mode)
{
case MSB_MODE:
val = 0x1b;
break;
case I2S_MODE:
val = 0x19;
break;
case LSB_MODE:
val = 0x1d;
break;
case PCM_MODE:
val = 0x1f;
break;
}
codecWriteVal(CODEC_ES8388, 0x17, val);
}

View File

@@ -0,0 +1,79 @@
#include "i2s.h"
#define NAU88C22_FS_NUM 256
i2sI2cCfg_t NAU88C22_slaveRegInfo[] =
{
{0x00,0x000},
{0x01,0x1FD},
{0x02,0x1BF},
{0x03,0x1EF},
//{0x04,0x008},
{0x06,0x000},
{0x0A,0x008},
//{0x0B,0x1FF},
//{0x0C,0x1FF},
{0x2C,0x033},
{0x2D,0x012},
{0x2E,0x012},
{0x32,0x001},
{0x33,0x001},
{0x34,0x139},
{0x35,0x139},
};
uint16_t NAU88C22GetRegCnt(char* regName)
{
if (strcmp(regName, "NAU88C22_slave") == 0)
{
return (sizeof(NAU88C22_slaveRegInfo) / sizeof(NAU88C22_slaveRegInfo[0]));
}
else if (strcmp(regName, "NAU88C22_master") == 0)
{
return (sizeof(NAU88C22_slaveRegInfo) / sizeof(NAU88C22_slaveRegInfo[0]));
}
return 0;
}
void codecI2cInit(void);
void codecI2cWrite(char* codecName, uint8_t slaveAddr, i2sI2cCfg_t* i2sI2cCfg);
uint8_t codecI2cRead(uint8_t slaveAddr, uint8_t regAddr);
void nau88c22MasterInit()
{
}
void nau88c22SlaveInit()
{
uint8_t dataRead = 0xff;
codecI2cInit();
for (int i = 0; i < NAU88C22GetRegCnt("NAU88C22_slave"); i++)
{
codecI2cWrite("NAU88C22", NAU88C22_IICADDR, (i2sI2cCfg_t*)&NAU88C22_slaveRegInfo[i]);
}
for (int i = 0; i < NAU88C22GetRegCnt("NAU88C22_slave"); i++)
{
dataRead = codecI2cRead(NAU88C22_IICADDR, NAU88C22_slaveRegInfo[i].regAddr);
printf("reg = 0x%02x, val = 0x%02x\n", NAU88C22_slaveRegInfo[i].regAddr, dataRead);
}
}
uint16_t NAU88C22GetFs()
{
return NAU88C22_FS_NUM;
}

View File

@@ -0,0 +1,323 @@
/****************************************************************************
*
* Copy right: 2018 Copyrigths of AirM2M Ltd.
* File name: bsp.c
* Description:
* History:
*
****************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "Driver_Common.h"
#include "clock.h"
#include "bsp.h"
#include "system_ec618.h"
#include DEBUG_LOG_HEADER_FILE
#include "ec_string.h"
#include "mem_map.h"
#if FEATURE_CCIO_ENABLE
#include "uart_device.h"
#endif
#include "dbversion.h"
#include "clock.h"
#include "hal_adcproxy.h"
#include "apmu_external.h"
extern ARM_DRIVER_USART Driver_USART0;
extern ARM_DRIVER_USART Driver_USART1;
ARM_DRIVER_USART *UsartPrintHandle = NULL;
ARM_DRIVER_USART *UsartUnilogHandle = NULL;
ARM_DRIVER_USART *UsartAtCmdHandle = NULL;
static uint8_t OSState = 0; // OSState = 0 os not start, OSState = 1 os started
extern void trimAdcSetGolbalVar(void);
void BSP_InitUartDriver(ARM_DRIVER_USART *drvHandler,
ARM_POWER_STATE powerMode,
uint32_t settings,
uint32_t baudRate,
ARM_USART_SignalEvent_t cb_event)
{
if(drvHandler)
{
drvHandler->Initialize(cb_event);
drvHandler->PowerControl(powerMode);
drvHandler->Control(settings, baudRate);
}
}
void BSP_DeinitUartDriver(ARM_DRIVER_USART *drvHandler)
{
if(drvHandler)
{
drvHandler->PowerControl(ARM_POWER_OFF);
drvHandler->Uninitialize();
}
}
#if defined ( __GNUC__ )
/*
* retarget for _write implementation
* Parameter: ch: character will be out
*/
int io_putchar(int ch)
{
if (UsartPrintHandle != NULL)
UsartPrintHandle->SendPolling((uint8_t*)&ch, 1);
return 0;
}
/*
* retarget for _read implementation
* Parameter: ch: character will be read
*/
int io_getchar()
{
uint8_t ch = 0;
if (UsartPrintHandle != NULL)
UsartPrintHandle->Receive(&ch, 1);
return (ch);
}
int fgetc(FILE *f)
{
uint8_t ch = 0;
if (UsartPrintHandle != NULL)
UsartPrintHandle->Receive(&ch, 1);
return (ch);
}
__attribute__((weak,noreturn))
void __aeabi_assert (const char *expr, const char *file, int line) {
printf("Assert, expr:%s, file: %s, line: %d\r\n", expr, file, line);
while(1);
}
void __assert_func(const char *filename, int line, const char *assert_func, const char *expr)
{
for(uint8_t i = 0; i<5; i++)
{
uniLogFlushOut();
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, assert_func_1, P_ERROR, "Assert, expr:%s, file: %s, line: %d\r\n", expr, filename, line);
}
while(1);
}
#elif defined (__CC_ARM)
/*
* retarget for printf implementation
* Parameter: ch: character will be out
* f: not used
*/
int fputc(int ch, FILE *f)
{
if (UsartPrintHandle != NULL)
UsartPrintHandle->SendPolling((uint8_t*)&ch,1);
return 0;
}
/*
* retarget for scanf implementation
* Parameter: f: not used
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
if (UsartPrintHandle != NULL)
UsartPrintHandle->Receive(&ch,1);
return (ch);
}
__attribute__((weak,noreturn))
void __aeabi_assert (const char *expr, const char *file, int line) {
printf("Assert, expr:%s, file: %s, line: %d\r\n", expr, file, line);
while(1);
}
#endif
uint32_t GET_PMU_RAWFLASH_OFFSET(void)
{
return FLASH_MEM_BACKUP_ADDR;
}
void setOSState(uint8_t state)
{
OSState = state;
}
PLAT_PA_RAMCODE uint8_t getOSState(void) //1 os started. 0 no OS or OS not started yet
{
return OSState;
}
uint8_t* getBuildInfo(void)
{
return (uint8_t *)BSP_HEADER;
}
uint8_t* getVersionInfo(void)
{
return (uint8_t *)VERSION_INFO;
}
uint8_t* getATIVersionInfo(void)
{
return (uint8_t *)ATI_VERSION_INFO;
}
//move here since this is an common and opensource place
uint8_t* getDebugDVersion(void)
{
return (uint8_t*)DB_VERSION_UNIQ_ID;
}
#ifdef UINILOG_FEATURE_ENABLE
/**
\fn void logToolCommandHandle(uint8_t *atcmd_buffer, uint32_t len)
\brief handle downlink command sent from unilog tool EPAT
if need to handle more command in future, add command-handler table
\param[in] event UART event, note used in this function
\param[in] cmd_buffer command received from UART
\param[in] len command length
\returns void
*/
void logToolCommandHandle(uint32_t event, uint8_t *cmd_buffer, uint32_t len)
{
(void)event;
uint8_t * LogDbVserion=getDebugDVersion();
if(ec_strnstr((const char *)cmd_buffer, "^logversion", len))
{
ECPLAT_PRINTF(UNILOG_PLA_INTERNAL_CMD, get_log_version, P_SIG, "LOGVERSION:%s",LogDbVserion);
}
else
{
ECPLAT_PRINTF(UNILOG_PLA_STRING, get_log_version_1, P_ERROR, "%s", "invalid command from EPAT");
}
return;
}
/**
* unilog entity is removed for the reason of BSP small image.
* for more implementation details, pls refer to
* gCustSerlEntity[CUST_ENTITY_UNILOG] in ccio_provider.c
*/
/*
* set unilog uart port
* Parameter: port: for unilog
* Parameter: baudrate: uart baudrate
*/
#ifdef __USER_CODE__
void SetUnilogUartOrg(usart_port_t port, uint32_t baudrate, bool startRecv)
#else
void SetUnilogUart(usart_port_t port, uint32_t baudrate, bool startRecv)
#endif
{
ARM_POWER_STATE powerMode = ARM_POWER_FULL;
uint32_t ctrlSetting = ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_8 | \
ARM_USART_PARITY_NONE | ARM_USART_STOP_BITS_1 | \
ARM_USART_FLOW_CONTROL_NONE;
if (port == PORT_USART_0)
{
#if (RTE_UART0)
UsartUnilogHandle = &CREATE_SYMBOL(Driver_USART, 0);
#endif
}
else if (port == PORT_USART_1)
{
#if (RTE_UART1)
UsartUnilogHandle = &CREATE_SYMBOL(Driver_USART, 1);
#endif
}
if (UsartUnilogHandle == NULL) return;
#ifdef FEATURE_CCIO_ENABLE
UartDevConf_t uartDevConf;
UartHwConf_t *uartHwConf = &uartDevConf.hwConf;
memset(&uartDevConf, 0, sizeof(UartDevConf_t));
uartHwConf->powerMode = powerMode;
uartHwConf->ctrlSetting = ctrlSetting;
uartHwConf->baudRate = baudrate;
uartDevConf.drvHandler = UsartUnilogHandle;
uartDevConf.mainUsage = CSIO_DT_DIAG;
uartDevConf.speedType = CCIO_ST_HIGH;
if(startRecv)
{
uartDevConf.bmCreateFlag = CCIO_TASK_FLAG_RX;
}
else
{
uartDevConf.bmCreateFlag = CCIO_TASK_FLAG_NONE;
}
uartDevCreate(port, &uartDevConf);
#else
BSP_InitUartDriver(UsartUnilogHandle, powerMode, ctrlSetting, baudrate, NULL);
#endif
}
void FlushUnilogOutput(void)
{
uniLogFlushOut();
if(UsartUnilogHandle == NULL)
return;
UsartUnilogHandle->Control(ARM_USART_CONTROL_FLUSH_TX, 0);
}
#endif
void BSP_CommonInit(void)
{
SystemCoreClockUpdate();
PAD_driverInit();
GPR_initialize();
trimAdcSetGolbalVar();
apmuInit();
//interrupt config
IC_PowupInit();
if(apmuGetAPBootFlag() == 0) // power on
{
apmuSetCPFastBoot(false); // set cp fast boot in case of cp dap wakeup
}
cpADCInit(); // enable adc ref output, need stable time
BOOT_TIMESTAMP_SET(1, 3);
}

View File

@@ -0,0 +1,121 @@
#include "cameraDrv.h"
camI2cCfg_t bf30a2_1sdrRegInfo[] =
{
{0xf2,0x01},//soft reset
{0xcf,0xb0},//power up
{0x12,0x20},//MTK:20 ZX:10 RDA:40
{0x15,0x80},
{0x6b,0x71},
{0x00,0x40},
{0x04,0x00},
{0x06,0x26},
{0x08,0x07},
{0x1c,0x12},
{0x20,0x20},
{0x21,0x20},
{0x34,0x02},
{0x35,0x02},
{0x36,0x21},
{0x37,0x13},
{0xca,0x23},
{0xcb,0x22},
{0xcc,0x89},
{0xcd,0x4c},
{0xce,0x6b},
{0xa0,0x8e},
{0x01,0x1b},
{0x02,0x1d},
{0x13,0x08},
{0x87,0x13},
{0x8b,0x08},
{0x70,0x1f},
{0x71,0x40},
{0x72,0x0a},
{0x73,0x62},
{0x74,0xa2},
{0x75,0xbf},
{0x76,0x02},
{0x77,0xcc},
{0x40,0x32},
{0x41,0x28},
{0x42,0x26},
{0x43,0x1d},
{0x44,0x1a},
{0x45,0x14},
{0x46,0x11},
{0x47,0x0f},
{0x48,0x0e},
{0x49,0x0d},
{0x4B,0x0c},
{0x4C,0x0b},
{0x4E,0x0a},
{0x4F,0x09},
{0x50,0x09},
{0x24,0x50},
{0x25,0x36},
{0x80,0x00},
{0x81,0x20},
{0x82,0x40},
{0x83,0x30},
{0x84,0x50},
{0x85,0x30},
{0x86,0xD8},
{0x89,0x45},
{0x8a,0x33},
{0x8f,0x81},
{0x91,0xff},
{0x92,0x08},
{0x94,0x82},
{0x95,0xfd},
{0x9a,0x20},
{0x9e,0xbc},
{0xf0,0x8f},
{0x51,0x06},
{0x52,0x25},
{0x53,0x2b},
{0x54,0x0F},
{0x57,0x2A},
{0x58,0x22},
{0x59,0x2c},
{0x23,0x33},
{0xa1,0x93},
{0xa2,0x0f},
{0xa3,0x2a},
{0xa4,0x08},
{0xa5,0x26},
{0xa7,0x80},
{0xa8,0x80},
{0xa9,0x1e},
{0xaa,0x19},
{0xab,0x18},
{0xae,0x50},
{0xaf,0x04},
{0xc8,0x10},
{0xc9,0x15},
{0xd3,0x0c},
{0xd4,0x16},
{0xee,0x06},
{0xef,0x04},
{0x55,0x34},
{0x56,0x9c},
{0xb1,0x98},
{0xb2,0x98},
{0xb3,0xc4},
{0xb4,0x0C},
{0xa0,0x8f},
{0x13,0x07},
};
uint16_t bf30a2GetRegCnt(char* regName)
{
if (strcmp(regName, "bf30a2_1sdr") == 0)
{
return (sizeof(bf30a2_1sdrRegInfo) / sizeof(bf30a2_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,99 @@
#include "cameraDrv.h"
#include "quirc.h"
static volatile bool isTransferDone;
extern void delay_us(uint32_t);
struct quirc *qr;
uint8_t* pic0Internal = NULL;
static void camRecvCb(uint32_t event)
{
if(event & ARM_SPI_EVENT_TRANSFER_COMPLETE)
{
isTransferDone = true;
}
}
bool decodeBegin(uint8_t* result)
{
int num_codes=0, w, h;
struct quirc_code code;
struct quirc_data data;
quirc_decode_error_t err;
quirc_begin(qr, &w, &h);
quirc_end(qr);
num_codes = quirc_count(qr);
if (num_codes != 1)
{
return false;
}
quirc_extract(qr, 0, &code);
/* Decoding stage */
err = quirc_decode(&code, &data);
if (err)
{
return false;
//printf("D F2: %s\n", quirc_strerror(err));
}
else
{
memcpy(result, data.payload, data.payload_len);
return true;
//printf("Data: %s\n", data.payload);
}
}
void camPrepare(uint8_t* pic0)
{
pic0Internal = pic0;
// Camera register part
camRegCfg(); // Only need to init once
// Quirc part
qr = quirc_new();
quirc_init(qr, pic0, 320, 240);
}
bool camBegin(bool start, uint8_t* result)
{
uint32_t timeOut_ms = 5000;
if (start)
{
camInit(camRecvCb);
camStart(true);
camRecv(pic0Internal);
do
{
delay_us(1000);
}
while((isTransferDone == false) && --timeOut_ms);
}
else
{
camStart(false);
return true;
}
if (isTransferDone)
{
isTransferDone = false;
return decodeBegin(result);
}
else
{
// Error: camera doesn't take picture fail
return false;
}
}

View File

@@ -0,0 +1,403 @@
#include "cameraDrv.h"
extern cspiDrvInterface_t cspiDrvInterface0;
extern cspiDrvInterface_t cspiDrvInterface1;
extern camI2cCfg_t sp0A39Cfg[];
extern camI2cCfg_t sp0821Cfg[];
extern camI2cCfg_t gc6123Cfg[];
extern camI2cCfg_t gc032ACfg[];
extern camI2cCfg_t bf30a2Cfg[];
extern cspiCtrl_t cspiCtrl;
extern cspiIntCtrl_t cspiIntCtrl;
extern cspiDataFmt_t cspiDataFmt;
extern ARM_DRIVER_I2C Driver_I2C0;
static ARM_DRIVER_I2C *i2cDrvInstance = &CREATE_SYMBOL(Driver_I2C, 0);
#define EIGEN_CSPI(n) ((CSPI_TypeDef *) (MP_I2S0_BASE_ADDR + 0x1000*n))
#if (CAMERA_ENABLE_SP0A39)
#if (SP0A39_2SDR)
char* regName = "sp0a39_2sdr";
#elif (SP0A39_1SDR)
char* regName = "sp0a39_1sdr";
#endif
#elif (CAMERA_ENABLE_SP0821)
#if (SP0821_2SDR)
char* regName = "sp0821_2sdr";
#elif (SP0821_1SDR)
char* regName = "sp0821_1sdr";
#endif
#elif (CAMERA_ENABLE_GC6123)
#if (GC6123_2SDR)
char* regName = "gc6123_2sdr";
#elif (GC6123_1SDR)
char* regName = "gc6123_1sdr";
#endif
#elif (CAMERA_ENABLE_GC032A)
#if (GC032A_2SDR)
char* regName = "gc032a_2sdr";
#elif (GC032A_1SDR)
char* regName = "gc032a_1sdr";
#endif
#elif (CAMERA_ENABLE_BF30A2)
#if (BF30A2_1SDR)
char* regName = "bf30a2_1sdr";
#endif
#elif (CAMERA_ENABLE_GC6153)
#if (GC6153_1SDR)
char* regName = "gc6153_1sdr";
#endif
#endif
static uint8_t slaveAddr;
static uint16_t regCnt;
static camI2cCfg_t* regInfo = NULL;
#if (RTE_CSPI1 == 1)
static cspiDrvInterface_t *cspiDrv = &CREATE_SYMBOL(cspiDrvInterface, 1);
#else
static cspiDrvInterface_t *cspiDrv = &CREATE_SYMBOL(cspiDrvInterface, 0);
#endif
extern void delay_us(uint32_t us);
void findRegInfo(char* regName, uint8_t* slaveAddr, uint16_t* regCnt, camI2cCfg_t** regInfo)
{
if (strcmp(regName, "sp0a39_2sdr") == 0)
{
extern camI2cCfg_t sp0A39_2sdrRegInfo[];
*regInfo = sp0A39_2sdrRegInfo;
*slaveAddr = SP0A39_I2C_ADDR;
*regCnt = sp0a39GetRegCnt(regName);
}
else if (strcmp(regName, "sp0a39_1sdr") == 0)
{
extern camI2cCfg_t sp0A39_1sdrRegInfo[];
*regInfo = sp0A39_1sdrRegInfo;
*slaveAddr = SP0A39_I2C_ADDR;
*regCnt = sp0a39GetRegCnt(regName);
}
else if (strcmp(regName, "sp0821_2sdr") == 0)
{
extern camI2cCfg_t sp0821_2sdrRegInfo[];
*regInfo = sp0821_2sdrRegInfo;
*slaveAddr = SP0821_I2C_ADDR;
*regCnt = sp0821GetRegCnt(regName);
}
else if (strcmp(regName, "sp0821_1sdr") == 0)
{
extern camI2cCfg_t sp0821_1sdrRegInfo[];
*regInfo = sp0821_1sdrRegInfo;
*slaveAddr = SP0821_I2C_ADDR;
*regCnt = sp0821GetRegCnt(regName);
}
else if (strcmp(regName, "gc6123_2sdr") == 0)
{
extern camI2cCfg_t gc6123_2sdrRegInfo[];
*regInfo = gc6123_2sdrRegInfo;
*slaveAddr = GC6123_I2C_ADDR;
*regCnt = gc6123GetRegCnt(regName);
}
else if (strcmp(regName, "gc6123_1sdr") == 0)
{
extern camI2cCfg_t gc6123_1sdrRegInfo[];
*regInfo = gc6123_1sdrRegInfo;
*slaveAddr = GC6123_I2C_ADDR;
*regCnt = gc6123GetRegCnt(regName);
}
else if (strcmp(regName, "gc032a_2sdr") == 0)
{
extern camI2cCfg_t gc032A_2sdrRegInfo[];
*regInfo = gc032A_2sdrRegInfo;
*slaveAddr = GC032A_I2C_ADDR;
*regCnt = gc032aGetRegCnt(regName);
}
else if (strcmp(regName, "gc032a_1sdr") == 0)
{
extern camI2cCfg_t gc032A_1sdrRegInfo[];
*regInfo = gc032A_1sdrRegInfo;
*slaveAddr = GC032A_I2C_ADDR;
*regCnt = gc032aGetRegCnt(regName);
}
else if (strcmp(regName, "bf30a2_1sdr") == 0)
{
extern camI2cCfg_t bf30a2_1sdrRegInfo[];
*regInfo = bf30a2_1sdrRegInfo;
*slaveAddr = BF30A2_I2C_ADDR;
*regCnt = bf30a2GetRegCnt(regName);
}
else if (strcmp(regName, "gc6153_1sdr") == 0)
{
extern camI2cCfg_t gc6153_1sdrRegInfo[];
*regInfo = gc6153_1sdrRegInfo;
*slaveAddr = GC6153_I2C_ADDR;
*regCnt = gc6153GetRegCnt(regName);
}
}
void camI2cInit()
{
i2cDrvInstance->Initialize(NULL);
i2cDrvInstance->PowerControl(ARM_POWER_FULL);
i2cDrvInstance->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_STANDARD);
i2cDrvInstance->Control(ARM_I2C_BUS_CLEAR, 0);
// Backup some info about this sensor
findRegInfo(regName, &slaveAddr, &regCnt, &regInfo);
}
void camI2cWrite(uint8_t slaveAddr, uint8_t regAddr, uint8_t regData, uint32_t num)
{
uint8_t tempBuffer[2];
tempBuffer[0] = regAddr;
tempBuffer[1] = regData;
i2cDrvInstance->MasterTransmit(slaveAddr, tempBuffer, num, false);
}
uint8_t camI2cRead(uint8_t slaveAddr, uint8_t regAddr)
{
uint8_t a;
a = regAddr;
uint8_t readData;
i2cDrvInstance->MasterTransmit(slaveAddr, (uint8_t *)&a, 1, true);
i2cDrvInstance->MasterReceive(slaveAddr, &readData, 1, false);
return readData;
}
uint8_t camReadReg(uint8_t regAddr)
{
uint8_t recvData;
recvData = camI2cRead(slaveAddr, regAddr);
return recvData;
}
void camWriteReg(camI2cCfg_t* regInfo)
{
camI2cWrite(slaveAddr, regInfo->regAddr, regInfo->regVal, 2);
}
void camRegCfg()
{
//uint8_t dataRead;
camI2cInit();
// Configure all the registers about this sensor
for (int i=0; i < regCnt; i++)
{
camI2cWrite(slaveAddr, regInfo[i].regAddr, regInfo[i].regVal, 2);
delay_us(10000); // delay 10ms
#if 0
dataRead = camI2cRead(slaveAddr, regInfo[i].regAddr);
printf("reg addr=0x%02x, reg val=0x%02x\n", regInfo[i].regAddr, dataRead);
delay_us(15000);
#endif
}
}
void camInterfaceCfg(camParamCfg_t* config)
{
cspiDataFmt.endianMode = config->endianMode;
cspiCtrl.rxWid = config->wireNum;
cspiCtrl.rxdSeq = config->rxSeq;
cspiCtrl.cpol = config->cpol;
cspiCtrl.cpha = config->cpha;
cspiCtrl.fillYonly = config->yOnly;
cspiCtrl.rowScaleRatio = config->rowScaleRatio;
cspiCtrl.colScaleRatio = config->colScaleRatio;
cspiCtrl.scaleBytes = config->scaleBytes;
}
void camSetMemAddr(uint32_t dataAddr)
{
cspiDrv->ctrl(CSPI_CTRL_MEM_ADDR , dataAddr); // register the recv memory
}
void camInit(void* dataAddr, cspiCbEvent_fn cb)
{
camResolution_e camResolution;
#if 0 // if used in os environment, use this api to adjust voltage
slpManNormalIOVoltSet(IOVOLT_3_00V);
#else // used in environment without os
// set all pin io to 2.7V since camera max voltage is 2.7V
GPR_clockEnable(PCLK_PMDIG);
*(uint32_t*)0x4d020018 = 1;
*(uint32_t*)0x4d040308 = 7; // 1:2.7V 7:3V
#endif
// Need to enable cspi first to make camera clock working
camParamCfg_t camParamCfg;
#if (CAMERA_ENABLE_SP0A39)
#if (SP0A39_2SDR)
camParamCfg.wireNum = WIRE_2;
#elif (SP0A39_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_0;
camParamCfg.cpha = 1;
camParamCfg.cpol = 0;
camResolution = CAM_CHAIN_COUNT;
#elif (CAMERA_ENABLE_SP0821)
#if (SP0821_2SDR)
camParamCfg.wireNum = WIRE_2;
#elif (SP0821_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_0;
camParamCfg.cpha = 1;
camParamCfg.cpol = 0;
camResolution = CAM_CHAIN_COUNT;
#elif (CAMERA_ENABLE_GC6123)
#if (GC6123_2SDR)
camParamCfg.wireNum = WIRE_2;
#elif (GC6123_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_1;
camParamCfg.cpha = 1;
camParamCfg.cpol = 0;
camParamCfg.yOnly = 1;
camParamCfg.rowScaleRatio = 0;
camParamCfg.colScaleRatio = 0;
camParamCfg.scaleBytes = 0;
camResolution = CAM_CHAIN_COUNT;
#elif (CAMERA_ENABLE_GC032A)
#if (GC032A_2SDR)
camParamCfg.wireNum = WIRE_2;
#elif (GC032A_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_0;
camParamCfg.cpha = 0;
camParamCfg.cpol = 0;
camResolution = CAM_CHAIN_COUNT;
if (camResolution == CAM_30W)
{
camParamCfg.yOnly = 0;
camParamCfg.rowScaleRatio = 0;
camParamCfg.colScaleRatio = 0;
camParamCfg.scaleBytes = 0;
}
else // CAM_8W
{
camParamCfg.yOnly = 1;
camParamCfg.rowScaleRatio = 1;
camParamCfg.colScaleRatio = 1;
camParamCfg.scaleBytes = 1;
}
#elif (CAMERA_ENABLE_BF30A2)
#if (BF30A2_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_0;
camParamCfg.cpha = 0;
camParamCfg.cpol = 0;
camParamCfg.yOnly = 1;
camParamCfg.rowScaleRatio = 0;
camParamCfg.colScaleRatio = 0;
camParamCfg.scaleBytes = 0;
camResolution = CAM_CHAIN_COUNT;
#elif (CAMERA_ENABLE_GC6153)
#if (GC6153_1SDR)
camParamCfg.wireNum = WIRE_1;
#endif
camParamCfg.endianMode = LSB_MODE;
camParamCfg.rxSeq = SEQ_1;
camParamCfg.cpha = 1;
camParamCfg.cpol = 0;
camParamCfg.yOnly = 1;
camParamCfg.rowScaleRatio = 0;
camParamCfg.colScaleRatio = 0;
camParamCfg.scaleBytes = 0;
camResolution = CAM_CHAIN_COUNT;
#endif
camInterfaceCfg(&camParamCfg);
cspiDrv->ctrl(CSPI_CTRL_MEM_ADDR , (uint32_t)dataAddr); // register the recv memory
cspiDrv->init(cb);
cspiDrv->powerCtrl(CSPI_POWER_FULL);
cspiDrv->ctrl(CSPI_CTRL_DATA_FORMAT , 0); // control cspi
cspiDrv->ctrl(CSPI_CTRL_RXTOR , 0);
cspiDrv->ctrl(CSPI_CTRL_FRAME_INFO0 , 0);
cspiDrv->ctrl(CSPI_CTRL_INT_CTRL , 0);
cspiDrv->ctrl(CSPI_CTRL_CSPICTL , 0);
cspiDrv->ctrl(CSPI_CTRL_DMA_CTRL , 0);
cspiDrv->ctrl(CSPI_CTRL_RESOLUTION_SET , camResolution);
cspiDrv->ctrl(CSPI_CTRL_BUS_SPEED, (camFrequence_e)CAM_25_5_M); // cspi working frequency
}
void camStartStop(cspiStartStop_e startStop)
{
cspiDrv->ctrl(CSPI_CTRL_START_STOP , (uint32_t)startStop);
}
void cspiIntEnable(cspiIntEnable_e intEnable)
{
cspiIntCtrl.frameStartIntEn = intEnable;
cspiDrv->ctrl(CSPI_CTRL_INT_CTRL , 0); // cspi interrupt enable or disable
}
void camFlush()
{
cspiDrv->ctrl(CSPI_CTRL_FLUSH_RX_FIFO , 0); // flush rx fifo
}
void camRegisterIRQ(cspiInstance_e instance, camIrq_fn irqCb)
{
IRQn_Type irqNum;
if (instance == CSPI_0)
{
irqNum = PXIC0_I2S0_IRQn;
}
else
{
irqNum = PXIC0_I2S1_IRQn;
}
XIC_SetVector(irqNum, irqCb);
XIC_EnableIRQ(irqNum);
}
PLAT_FM_RAMCODE void camRecv(uint8_t * dataAddr)
{
cspiDrv->ctrl(CSPI_CTRL_MEM_ADDR , (uint32_t)dataAddr); // register the recv memory
cspiDrv->recv();
}
uint32_t camGetCspiStats(cspiInstance_e instance)
{
return EIGEN_CSPI(instance)->STAS;
}
void camClearIntStats(cspiInstance_e instance, uint32_t mask)
{
EIGEN_CSPI(instance)->STAS = mask;
}

View File

@@ -0,0 +1,666 @@
#include "cameraDrv.h"
camI2cCfg_t gc032A_2sdrRegInfo[] =
{
{0xf3,0x83},
{0xf5,0x0c},
{0xf7,0x01},// gavin 20160820
{0xf8,0x01},
{0xf9,0x4e},
{0xfa,0x10}, // gavin 20160820
{0xfc,0x02},
{0xfe,0x02},
{0x81,0x03},
{0xfe,0x00},
{0x77,0x64},
{0x78,0x40},
{0x79,0x60},
/*Analog&Cisctl*/
{0xfe,0x00},
{0x03,0x01},
{0x04,0xc2},
{0x05,0x01},
{0x06,0xb8},
{0x07,0x00},
{0x08,0x08},
{0x0a,0x00},
{0x0c,0x00},
{0x0d,0x01},
{0x0e,0xe8},
{0x0f,0x02},
{0x10,0x88},
{0x17,0x54},
{0x19,0x08},
{0x1a,0x0a},
{0x1f,0x40},
{0x20,0x30},
{0x2e,0x80},
{0x2f,0x2b},
{0x30,0x1a},
{0xfe,0x02},
{0x03,0x02},
{0x05,0xd7},
{0x06,0x60},
{0x08,0x80},
{0x12,0x89},
/*SPI*/
{0xfe,0x03},
{0x51,0x01},
{0x52,0x58}, // DDR Disable gavin 20160820
{0x53,0x24}, // Disable CRC
{0x54,0x20},
{0x55,0x00},
{0x59,0x10},
{0x5a,0x00},
{0x5b,0x80},
{0x5c,0x02},
{0x5d,0xe0},
{0x5e,0x01},
{0x64,0x04}, //SCK Always OFF , gavin 20160820
/*blk*/
{0xfe,0x00},
{0x18,0x02},
{0xfe,0x02},
{0x40,0x22},
{0x45,0x00},
{0x46,0x00},
{0x49,0x20},
{0x4b,0x3c},
{0x50,0x20},
{0x42,0x10},
/*isp*/
{0xfe,0x01},
{0x0a,0xc5},
{0x45,0x00},
{0xfe,0x00},
{0x40,0xff},
{0x41,0x25},
{0x42,0xcf},
{0x43,0x10},
{0x44,0x83},
{0x46,0x22},
{0x49,0x03},
{0x52,0x02},
{0x54,0x00},
{0xfe,0x02},
{0x22,0xf6},
/*Shading*/
{0xfe,0x01},
{0xc1,0x38},
{0xc2,0x4c},
{0xc3,0x00},
{0xc4,0x32},
{0xc5,0x24},
{0xc6,0x16},
{0xc7,0x08},
{0xc8,0x08},
{0xc9,0x00},
{0xca,0x20},
{0xdc,0x8a},
{0xdd,0xa0},
{0xde,0xa6},
{0xdf,0x75},
/*AWB*//*20170110*/
{0xfe, 0x01},
{0x7c, 0x09},
{0x65, 0x06},
{0x7c, 0x08},
{0x56, 0xf4},
{0x66, 0x0f},
{0x67, 0x84},
{0x6b, 0x80},
{0x6d, 0x12},
{0x6e, 0xb0},
{0xfe, 0x01},
{0x90, 0x00},
{0x91, 0x00},
{0x92, 0xf4},
{0x93, 0xd5},
{0x95, 0x0f},
{0x96, 0xf4},
{0x97, 0x2d},
{0x98, 0x0f},
{0x9a, 0x2d},
{0x9b, 0x0f},
{0x9c, 0x59},
{0x9d, 0x2d},
{0x9f, 0x67},
{0xa0, 0x59},
{0xa1, 0x00},
{0xa2, 0x00},
{0x86, 0x00},
{0x87, 0x00},
{0x88, 0x00},
{0x89, 0x00},
{0xa4, 0x00},
{0xa5, 0x00},
{0xa6, 0xd4},
{0xa7, 0x9f},
{0xa9, 0xd4},
{0xaa, 0x9f},
{0xab, 0xac},
{0xac, 0x9f},
{0xae, 0xd4},
{0xaf, 0xac},
{0xb0, 0xd4},
{0xb1, 0xa3},
{0xb3, 0xd4},
{0xb4, 0xac},
{0xb5, 0x00},
{0xb6, 0x00},
{0x8b, 0x00},
{0x8c, 0x00},
{0x8d, 0x00},
{0x8e, 0x00},
{0x94, 0x50},
{0x99, 0xa6},
{0x9e, 0xaa},
{0xa3, 0x0a},
{0x8a, 0x00},
{0xa8, 0x50},
{0xad, 0x55},
{0xb2, 0x55},
{0xb7, 0x05},
{0x8f, 0x00},
{0xb8, 0xb3},
{0xb9, 0xb6},
/*CC*/
{0xfe,0x01},
{0xd0,0x40},
{0xd1,0xf8},
{0xd2,0x00},
{0xd3,0xfa},
{0xd4,0x45},
{0xd5,0x02},
{0xd6,0x30},
{0xd7,0xfa},
{0xd8,0x08},
{0xd9,0x08},
{0xda,0x58},
{0xdb,0x02},
{0xfe,0x00},
/*Gamma*/
{0xfe,0x00},
{0xba,0x00},
{0xbb,0x04},
{0xbc,0x0a},
{0xbd,0x0e},
{0xbe,0x22},
{0xbf,0x30},
{0xc0,0x3d},
{0xc1,0x4a},
{0xc2,0x5d},
{0xc3,0x6b},
{0xc4,0x7a},
{0xc5,0x85},
{0xc6,0x90},
{0xc7,0xa5},
{0xc8,0xb5},
{0xc9,0xc2},
{0xca,0xcc},
{0xcb,0xd5},
{0xcc,0xde},
{0xcd,0xea},
{0xce,0xf5},
{0xcf,0xff},
/*Auto Gamma*/
{0xfe,0x00},
{0x5a,0x08},
{0x5b,0x0f},
{0x5c,0x15},
{0x5d,0x1c},
{0x5e,0x28},
{0x5f,0x36},
{0x60,0x45},
{0x61,0x51},
{0x62,0x6a},
{0x63,0x7d},
{0x64,0x8d},
{0x65,0x98},
{0x66,0xa2},
{0x67,0xb5},
{0x68,0xc3},
{0x69,0xcd},
{0x6a,0xd4},
{0x6b,0xdc},
{0x6c,0xe3},
{0x6d,0xf0},
{0x6e,0xf9},
{0x6f,0xff},
/*Gain*/
{0xfe,0x00},
{0x70,0x50},
/*AEC*/
{0xfe,0x00},
{0x4f,0x01},
{0xfe,0x01},
{0x0d,0x00},//08 add 20170110
{0x12,0xa0},
{0x13,0x3a},
{0x44,0x04},
{0x1f,0x30},
{0x20,0x40},
{0x26,0x9a},
{0x3e,0x20},
{0x3f,0x2d},
{0x40,0x40},
{0x41,0x5b},
{0x42,0x82},
{0x43,0xb7},
{0x04,0x0a},
{0x02,0x79},
{0x03,0xc0},
/*measure window*/
{0xfe,0x01},
{0xcc,0x08},
{0xcd,0x08},
{0xce,0xa4},
{0xcf,0xec},
/*DNDD*/
{0xfe,0x00},
{0x81,0xb8},
{0x82,0x12},
{0x83,0x0a},
{0x84,0x01},
{0x86,0x50},
{0x87,0x18},
{0x88,0x10},
{0x89,0x70},
{0x8a,0x20},
{0x8b,0x10},
{0x8c,0x08},
{0x8d,0x0a},
/*Intpee*/
{0xfe,0x00},
{0x8f,0xaa},
{0x90,0x9c},
{0x91,0x52},
{0x92,0x03},
{0x93,0x03},
{0x94,0x08},
{0x95,0x44},
{0x97,0x00},
{0x98,0x00},
/*ASDE*/
{0xfe,0x00},
{0xa1,0x30},
{0xa2,0x41},
{0xa4,0x30},
{0xa5,0x20},
{0xaa,0x30},
{0xac,0x32},
/*YCP*/
{0xfe,0x00},
{0xd1,0x3c},
{0xd2,0x3c},
{0xd3,0x38},
{0xd6,0xf4},
{0xd7,0x1d},
{0xdd,0x73},
{0xde,0x84},
{0xfe,0x00},
{0x05,0x01},
{0x06,0xad},
{0x07,0x00},
{0x08,0x10},
{0xfe,0x01},
{0x25,0x00},
{0x26,0x4d},
{0x27,0x01},
{0x28,0xce},
{0x29,0x03},
{0x2a,0x02},
{0x2b,0x03},
{0x2c,0x9c},
{0x2d,0x04},
{0x2e,0x36},
{0x2f,0x04},
{0x30,0xd0},
{0x31,0x05},
{0x32,0x6a},
{0x33,0x06},
{0x34,0x04},
{0xfe,0x00},
};
camI2cCfg_t gc032A_1sdrRegInfo[] =
{
{0xf3,0x83}, //sync_output_en data_output_en
{0xf5,0x0c},
{0xf7,0x01},
{0xf8,0x01},
{0xf9,0x4e},
{0xfa,0x30},
{0xfc,0x02},
{0xfe,0x02},
{0x81,0x03}, // doesn't show 0x81 addr
/*Analog*/
{0xfe,0x00},
{0x03,0x01}, // exposure high
{0x04,0xc2}, // exposure low
{0x05,0x01},
{0x06,0x91},
{0x07,0x00},
{0x08,0x10},
{0x0a,0x04},
{0x0c,0x04},
{0x0d,0x01},
{0x0e,0xe8}, // height: 488
{0x0f,0x02},
{0x10,0x88}, // width: 652 VGA: 640*480
{0x17,0x54},
{0x19,0x04},
{0x1a,0x0a},
{0x1f,0x40},
{0x20,0x30},
{0x2e,0x80},
{0x2f,0x2b},
{0x30,0x1a},
{0xfe,0x02},
{0x03,0x02},
{0x05,0xd7},
{0x06,0x60},
{0x08,0x80},
{0x12,0x89},
/*blk*/
{0xfe,0x00},
{0x18,0x02},
{0xfe,0x02},
{0x40,0x22},
{0x45,0x00},
{0x46,0x00},
{0x49,0x20},
{0x4b,0x3c},
{0x50,0x20},
{0x42,0x10},
/*isp*/
{0xfe,0x01},
{0x0a,0xc5},
{0x45,0x00},
{0xfe,0x00},
{0x40,0xff},
{0x41,0x25},
{0x42,0x83},
{0x43,0x10},
{0x44,0x83},
{0x46,0x26},
{0x49,0x03},
{0x4f,0x01},
{0xde,0x84},
{0xfe,0x02},
{0x22,0xf6},
/*Shading*/
{0xfe,0x00},
{0x77,0x65},
{0x78,0x40},
{0x79,0x52},
{0xfe,0x01},
{0xc1,0x3c},
{0xc2,0x50},
{0xc3,0x00},
{0xc4,0x32},
{0xc5,0x24},
{0xc6,0x16},
{0xc7,0x08},
{0xc8,0x08},
{0xc9,0x00},
{0xca,0x20},
{0xdc,0x7a},
{0xdd,0x7a},
{0xde,0xa6},
{0xdf,0x60},
/*AWB*/
{0xfe,0x01},
{0x7c,0x09},
{0x65,0x06},
{0x7c,0x08},
{0x56,0xf4},
{0x66,0x0f},
{0x67,0x84},
{0x6b,0x80},
{0x6d,0x12},
{0x6e,0xb0},
{0x86,0x00},
{0x87,0x00},
{0x88,0x00},
{0x89,0x00},
{0x8a,0x00},
{0x8b,0x00},
{0x8c,0x00},
{0x8d,0x00},
{0x8e,0x00},
{0x8f,0x00},
{0x90,0xef},
{0x91,0xe1},
{0x92,0x0c},
{0x93,0xef},
{0x94,0x65},
{0x95,0x1f},
{0x96,0x0c},
{0x97,0x2d},
{0x98,0x20},
{0x99,0xaa},
{0x9a,0x3f},
{0x9b,0x2c},
{0x9c,0x5f},
{0x9d,0x3e},
{0x9e,0xaa},
{0x9f,0x67},
{0xa0,0x60},
{0xa1,0x00},
{0xa2,0x00},
{0xa3,0x0a},
{0xa4,0xb6},
{0xa5,0xac},
{0xa6,0xc1},
{0xa7,0xac},
{0xa8,0x55},
{0xa9,0xc3},
{0xaa,0xa4},
{0xab,0xba},
{0xac,0xa8},
{0xad,0x55},
{0xae,0xc8},
{0xaf,0xb9},
{0xb0,0xd4},
{0xb1,0xc3},
{0xb2,0x55},
{0xb3,0xd8},
{0xb4,0xce},
{0xb5,0x00},
{0xb6,0x00},
{0xb7,0x05},
{0xb8,0xd6},
{0xb9,0x8c},
/*CC*/
{0xfe,0x01},
{0xd0,0x40},
{0xd1,0xf8},
{0xd2,0x00},
{0xd3,0xfa},
{0xd4,0x45},
{0xd5,0x02},
{0xd6,0x30},
{0xd7,0xfa},
{0xd8,0x08},
{0xd9,0x08},
{0xda,0x58},
{0xdb,0x02},
{0xfe,0x00},
/*Gamma*/
{0xfe,0x00},
{0xba,0x00},
{0xbb,0x04},
{0xbc,0x0a},
{0xbd,0x0e},
{0xbe,0x22},
{0xbf,0x30},
{0xc0,0x3d},
{0xc1,0x4a},
{0xc2,0x5d},
{0xc3,0x6b},
{0xc4,0x7a},
{0xc5,0x85},
{0xc6,0x90},
{0xc7,0xa5},
{0xc8,0xb5},
{0xc9,0xc2},
{0xca,0xcc},
{0xcb,0xd5},
{0xcc,0xde},
{0xcd,0xea},
{0xce,0xf5},
{0xcf,0xff},
/*Auto Ga*/
{0xfe,0x00},
{0x5a,0x08},
{0x5b,0x0f},
{0x5c,0x15},
{0x5d,0x1c},
{0x5e,0x28},
{0x5f,0x36},
{0x60,0x45},
{0x61,0x51},
{0x62,0x6a},
{0x63,0x7d},
{0x64,0x8d},
{0x65,0x98},
{0x66,0xa2},
{0x67,0xb5},
{0x68,0xc3},
{0x69,0xcd},
{0x6a,0xd4},
{0x6b,0xdc},
{0x6c,0xe3},
{0x6d,0xf0},
{0x6e,0xf9},
{0x6f,0xff},
/*Gain*/
{0xfe,0x00},
{0x70,0x50},
/*AEC*/
{0xfe,0x00},
{0x4f,0x01},
{0xfe,0x01},
{0x12,0xa0},
{0x13,0x3a},
{0x44,0x04},
{0x1f,0x30},
{0x20,0x40},
{0x26,0x14},
{0x27,0x01},
{0x28,0xf4},
{0x29,0x02},
{0x2a,0x3a},
{0x2b,0x02},
{0x2c,0xac},
{0x2d,0x02},
{0x2e,0xf8},
{0x2f,0x0b},
{0x30,0x6e},
{0x31,0x0e},
{0x32,0x70},
{0x33,0x12},
{0x34,0x0c},
{0x3c,0x00},
{0x3e,0x20},
{0x3f,0x2d},
{0x40,0x40},
{0x41,0x5b},
{0x42,0x82},
{0x43,0xb7},
{0x04,0x0a},
{0x02,0x79},
{0x03,0xc0},
/*measure*/
{0xcc,0x08},
{0xcd,0x08},
{0xce,0xa4},
{0xcf,0xec},
/*DNDD*/
{0xfe,0x00},
{0x81,0xb8},
{0x82,0x12},
{0x83,0x0a},
{0x84,0x01},
{0x86,0x50},
{0x87,0x18},
{0x88,0x10},
{0x89,0x70},
{0x8a,0x20},
{0x8b,0x10},
{0x8c,0x08},
{0x8d,0x0a},
/*Intpee*/
{0xfe,0x00},
{0x8f,0xaa},
{0x90,0x9c},
{0x91,0x52},
{0x92,0x03},
{0x93,0x03},
{0x94,0x08},
{0x95,0x44},
{0x97,0x00},
{0x98,0x00},
/*ASDE*/
{0xfe,0x00},
{0xa1,0x30},
{0xa2,0x41},
{0xa4,0x30},
{0xa5,0x20},
{0xaa,0x30},
{0xac,0x32},
/*YCP*/
{0xfe,0x00},
{0xd1,0x3c},
{0xd2,0x3c},
{0xd3,0x38},
{0xd6,0xf4},
{0xd7,0x1d},
{0xdd,0x73},
{0xde,0x84},
/*SPI*/
{0xfe,0x03}, // registers in REGF3
{0x51,0x01},
{0x52,0x0a}, // Y: 266
{0x53,0x20}, // ֻ<><D6BB>2bit<69><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0x20?
{0x54,0x20}, // X: 0x220 = 544
{0x55,0x00},
{0x59,0x10},
{0x5a,0x00}, // sync format<61><74>
{0x5b,0x80},
{0x5c,0x02}, // image width<74><68>640
{0x5d,0xe0},
{0x5e,0x01}, // image height<68><74>480
};
uint16_t gc032aGetRegCnt(char* regName)
{
if (strcmp(regName, "gc032a_2sdr") == 0)
{
return (sizeof(gc032A_2sdrRegInfo) / sizeof(gc032A_2sdrRegInfo[0]));
}
else if (strcmp(regName, "gc032a_1sdr") == 0)
{
return (sizeof(gc032A_1sdrRegInfo) / sizeof(gc032A_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,360 @@
#include "cameraDrv.h"
camI2cCfg_t gc6123_2sdrRegInfo[] =
{
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xf1, 0x07}, //output enable
{0xf4, 0x00},
//{0xf7, 0x00},
//{0xfa, 0x00},
{0xfc, 0x16}, //clock enable
{0xfe , 0x00},
{0x08, 0x02}, //col start
{0x09, 0x01}, //window height
{0x0a, 0x48},
{0x0b, 0x00}, //window width
{0x0c, 0xf4},
{0x10, 0x48}, //sh_width
{0x11, 0x1d}, //tx_width
{0x14, 0x14}, //dark CFA
{0x15, 0x0a}, //sdark
{0x16, 0x04}, //AD pipe number
{0x18, 0xc2}, //rowsg_gap
{0x1a, 0x17}, //clk_delay_en
{0x1b, 0x1a}, //20121107 comv_r solve FPN-W/18 //70/adclk mode
{0x1c, 0x49}, //txhigh_en
{0x1d, 0xb0}, //vref
{0x1e, 0x52}, //20131231/53//20130306/52 //20121107 solve OBI/51 //ADC_r
//{0x1f, 0x3f},
/////////////////////////////////////////////////////
////////////////////// ISP //////////////////////
/////////////////////////////////////////////////////
{0x20,0x5e},
{0x21,0x38}, //autogray
{0x22,0x92}, //20121107 auto_DD_en/82 //02
{0x24,0xa2}, //output_format
{0x26,0x03},
{0x27,0x90}, //clock gating
{0x28,0x8c},
{0x38,0x80}, //crop
{0x3b,0x01},
{0x3c,0x40},
{0x3d,0x00},
{0x3e,0xf0},
/////////////////////////////////////////////////////
////////////////////// BLK //////////////////////
/////////////////////////////////////////////////////
{0x2a, 0x65}, //2f/BLK row select
{0x2c, 0x40}, //global offset
/////////////////////////////////////////////////////
////////////////////// GAIN /////////////////////
/////////////////////////////////////////////////////
{0x3f, 0x12}, //20/global gain
/////////////////////////////////////////////////////
////////////////////// DNDD /////////////////////
/////////////////////////////////////////////////////
{0x50, 0x45},
{0x52, 0x4f}, //6c/DN b
{0x53, 0x81}, //a5/DN C
{0x58, 0x6f}, //20121107 dark_th 64
{0xc3, 0x96}, //00
/////////////////////////////////////////////////////
////////////////////// ASDE /////////////////////
/////////////////////////////////////////////////////
{0xac, 0xb5},
{0x5c, 0x80}, //60/OT_th
/////////////////////////////////////////////////////
///////////////////// INTPEE ////////////////////
/////////////////////////////////////////////////////
{0x63, 0x03}, //04/edge effect
{0x65, 0x23}, //43/42/edge max/min
/////////////////////////////////////////////////////
///////////////////// GAMMA /////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
////////////////////// CC ///////////////////////
/////////////////////////////////////////////////////
{0x66, 0x13},
{0x67, 0x26},
{0x68, 0x07},
{0x69, 0xf5},
{0x6a, 0xea},
{0x6b, 0x21},
{0x6c, 0x21},
{0x6d, 0xe4},
{0x6e, 0xfb},
/////////////////////////////////////////////////////
////////////////////// YCP //////////////////////
/////////////////////////////////////////////////////
{0x81, 0x48}, //38//cb
{0x82, 0x48}, //38//cr
{0x83, 0x4b}, //40/luma contrast
{0x84, 0x80}, //90/contrast center
{0x85, 0x00}, //06/luma offset
{0x86, 0xfb}, //skin cb
{0x87, 0x1d}, //skin cr
{0x88, 0x18}, //skin radius
{0x8d, 0x78}, //38/edge dec sa
{0x8e, 0x25}, //autogray
/////////////////////////////////////////////////////
////////////////////// AEC //////////////////////
/////////////////////////////////////////////////////
{0xa4, 0x01},
{0x9e, 0x01}, // increase fps
{0x9f, 0x90}, // 0x1c
{0xa0, 0x10},
{0x90, 0x4a}, //0a //48
{0x92, 0x40}, //40/target Y
{0xa2, 0x40}, //max_post_gain
{0xa3, 0x80}, //max_pre_gain
/////////////////////////////////////////////////////
////////////////////// AWB //////////////////////
/////////////////////////////////////////////////////
{0xb0, 0xf8}, //f5/RGB high low
{0xb1, 0x24}, //18/Y to C
{0xb3, 0x20}, //0d/C max
{0xb4, 0x2d}, //22/C inter
{0xb5, 0x1b}, //22/C inter
{0xb6, 0x2e}, //C inter2
{0xb7, 0x18}, //40/C inter3
{0xb8, 0x13}, //20/number limit
{0xb9, 0x33},
{0xba, 0x21},
{0xbb, 0x61}, //42/speed & margin
{0xbf, 0x68}, //78/b limit
{0x4c, 0x08},
{0x4d, 0x06},
{0x4e, 0x7b},
{0x4f, 0xa0},
{0xfe, 0x02},
{0x01, 0x03},
{0x02, 0x02}, //LSB & Falling edge sample
//{0x03, 0x20}, //1-wire
{0x04, 0x20}, //[4] master_outformat
{0x05, 0x00},
{0x09, 0x00}, //Reverse the high<->low byte.
{0x0a, 0x00}, //Data ID, 0x00-YUV422, 0x01-RGB565
{0x13, 0xf0},
/////////////////////////////////////////////////////
///////////////////// 2-wire ////////////////////
/////////////////////////////////////////////////////
{0x03, 0x25}, //20
{0xfd, 0x04},
{0xf1, 0x07}, //00
/////////////////////////////////////////////////////
///////////////////// 1-wire ////////////////////
/////////////////////////////////////////////////////
//{0x03, 0x20}, //20
//{0xfd, 0x00}, //00
//{0xf1, 0x05},
{0xfe, 0x00},
};
camI2cCfg_t gc6123_1sdrRegInfo[] =
{
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xf1, 0x07}, //output enable
{0xf4, 0x00},
//{0xf7, 0x00},
//{0xfa, 0x00},
{0xfc, 0x16}, //clock enable
{0xfe , 0x00},
{0x08, 0x02}, //col start
{0x09, 0x01}, //window height
{0x0a, 0x48},
{0x0b, 0x00}, //window width
{0x0c, 0xf4},
{0x10, 0x48}, //sh_width
{0x11, 0x1d}, //tx_width
{0x14, 0x14}, //dark CFA
{0x15, 0x0a}, //sdark
{0x16, 0x04}, //AD pipe number
{0x18, 0xc2}, //rowsg_gap
{0x1a, 0x17}, //clk_delay_en
{0x1b, 0x1a}, //20121107 comv_r solve FPN-W/18 //70/adclk mode
{0x1c, 0x49}, //txhigh_en
{0x1d, 0xb0}, //vref
{0x1e, 0x52}, //20131231/53//20130306/52 //20121107 solve OBI/51 //ADC_r
//{0x1f, 0x3f},
/////////////////////////////////////////////////////
////////////////////// ISP //////////////////////
/////////////////////////////////////////////////////
{0x20,0x5e},
{0x21,0x38}, //autogray
{0x22,0x92}, //20121107 auto_DD_en/82 //02
{0x24,0xa2}, //output_format
{0x26,0x03},
{0x27,0x90}, //clock gating
{0x28,0x8c},
{0x38,0x80}, //crop
{0x3b,0x01},
{0x3c,0x40},
{0x3d,0x00},
{0x3e,0xf0},
/////////////////////////////////////////////////////
////////////////////// BLK //////////////////////
/////////////////////////////////////////////////////
{0x2a, 0x65}, //2f/BLK row select
{0x2c, 0x40}, //global offset
/////////////////////////////////////////////////////
////////////////////// GAIN /////////////////////
/////////////////////////////////////////////////////
{0x3f, 0x12}, //20/global gain
/////////////////////////////////////////////////////
////////////////////// DNDD /////////////////////
/////////////////////////////////////////////////////
{0x50, 0x45},
{0x52, 0x4f}, //6c/DN b
{0x53, 0x81}, //a5/DN C
{0x58, 0x6f}, //20121107 dark_th 64
{0xc3, 0x96}, //00
/////////////////////////////////////////////////////
////////////////////// ASDE /////////////////////
/////////////////////////////////////////////////////
{0xac, 0xb5},
{0x5c, 0x80}, //60/OT_th
/////////////////////////////////////////////////////
///////////////////// INTPEE ////////////////////
/////////////////////////////////////////////////////
{0x63, 0x03}, //04/edge effect
{0x65, 0x23}, //43/42/edge max/min
/////////////////////////////////////////////////////
///////////////////// GAMMA /////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
////////////////////// CC ///////////////////////
/////////////////////////////////////////////////////
{0x66, 0x13},
{0x67, 0x26},
{0x68, 0x07},
{0x69, 0xf5},
{0x6a, 0xea},
{0x6b, 0x21},
{0x6c, 0x21},
{0x6d, 0xe4},
{0x6e, 0xfb},
/////////////////////////////////////////////////////
////////////////////// YCP //////////////////////
/////////////////////////////////////////////////////
{0x81, 0x48}, //38//cb
{0x82, 0x48}, //38//cr
{0x83, 0x4b}, //40/luma contrast
{0x84, 0x80}, //90/contrast center
{0x85, 0x00}, //06/luma offset
{0x86, 0xfb}, //skin cb
{0x87, 0x1d}, //skin cr
{0x88, 0x18}, //skin radius
{0x8d, 0x78}, //38/edge dec sa
{0x8e, 0x25}, //autogray
/////////////////////////////////////////////////////
////////////////////// AEC //////////////////////
/////////////////////////////////////////////////////
{0xa4, 0x01},
{0x9e, 0x01}, // 0x02
{0x9f, 0x90}, // 0x1c
{0xa0, 0x10},
{0x90, 0x4a}, //0a //48
{0x92, 0x40}, //40/target Y
{0xa2, 0x40}, //max_post_gain
{0xa3, 0x80}, //max_pre_gain
/////////////////////////////////////////////////////
////////////////////// AWB //////////////////////
/////////////////////////////////////////////////////
{0xb0, 0xf8}, //f5/RGB high low
{0xb1, 0x24}, //18/Y to C
{0xb3, 0x20}, //0d/C max
{0xb4, 0x2d}, //22/C inter
{0xb5, 0x1b}, //22/C inter
{0xb6, 0x2e}, //C inter2
{0xb7, 0x18}, //40/C inter3
{0xb8, 0x13}, //20/number limit
{0xb9, 0x33},
{0xba, 0x21},
{0xbb, 0x61}, //42/speed & margin
{0xbf, 0x68}, //78/b limit
{0x4c, 0x08},
{0x4d, 0x06},
{0x4e, 0x7b},
{0x4f, 0xa0},
{0xfe, 0x02},
{0x01, 0x03},
{0x02, 0x02}, //LSB & Falling edge sample
//{0x03, 0x20}, //1-wire
{0x04, 0x20}, //[4] master_outformat
{0x05, 0x00},
{0x09, 0x00}, //Reverse the high<->low byte.
{0x0a, 0x00}, //Data ID, 0x00-YUV422, 0x01-RGB565
{0x13, 0xf0},
/////////////////////////////////////////////////////
///////////////////// 2-wire ////////////////////
/////////////////////////////////////////////////////
// {0x03, 0x25}, //20
// {0xfd, 0x04},
// {0xf1, 0x07}, //00
/////////////////////////////////////////////////////
///////////////////// 1-wire ////////////////////
/////////////////////////////////////////////////////
{0x03, 0x20}, //20
{0xfd, 0x00}, //00
{0xf1, 0x05},
{0xfe, 0x00},
};
uint16_t gc6123GetRegCnt(char* regName)
{
if (strcmp(regName, "gc6123_2sdr") == 0)
{
return (sizeof(gc6123_2sdrRegInfo) / sizeof(gc6123_2sdrRegInfo[0]));
}
else if (strcmp(regName, "gc6123_1sdr") == 0)
{
return (sizeof(gc6123_1sdrRegInfo) / sizeof(gc6123_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,171 @@
#include "cameraDrv.h"
camI2cCfg_t gc6153_1sdrRegInfo[] =
{
// SYS
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xfe, 0xa0},
{0xfa, 0x11},
{0xfc, 0x00},
{0xf6, 0x00},
{0xfc, 0x12},
// ANALOG & CISCTL
{0xfe, 0x00},
{0x01, 0x40},
{0x02, 0x12},
{0x0d, 0x40},
{0x14, 0x7c}, // 0x7e
{0x16, 0x05}, // 0x05
{0x17, 0x18}, // 0x18
{0x1c, 0x31},
{0x1d, 0xbb},
{0x1f, 0x3f},
{0x73, 0x20},
{0x74, 0x71},
{0x77, 0x22},
{0x7a, 0x08},
{0x11, 0x18},
{0x13, 0x48},
{0x12, 0xc8},
{0x70, 0xc8},
{0x7b, 0x18},
{0x7d, 0x30},
{0x7e, 0x02},
{0xfe, 0x10},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x00},
{0xfe, 0x10},
{0xfe, 0x00},
{0x49, 0x61},
{0x4a, 0x40},
{0x4b, 0x58},
/*ISP*/
{0xfe, 0x00},
{0x39, 0x02},
{0x3a, 0x80},
{0x20, 0x7e},
{0x26, 0xa7},
/*BLK*/
{0x33, 0x10},
{0x37, 0x06},
{0x2a, 0x21},
/*GAIN*/
{0x3f, 0x16},
/*DNDD*/
{0x52, 0xa6},
{0x53, 0x81},
{0x54, 0x43},
{0x56, 0x78},
{0x57, 0xaa},
{0x58, 0xff},
/*ASDE*/
{0x5b, 0x60},
{0x5c, 0x50},
{0xab, 0x2a},
{0xac, 0xb5},
/*INTPEE*/
{0x5e, 0x06},
{0x5f, 0x06},
{0x60, 0x44},
{0x61, 0xff},
{0x62, 0x69},
{0x63, 0x13},
/*CC*/
{0x65, 0x13},
{0x66, 0x26},
{0x67, 0x07},
{0x68, 0xf5},
{0x69, 0xea},
{0x6a, 0x21},
{0x6b, 0x21},
{0x6c, 0xe4},
{0x6d, 0xfb},
/*YCP*/
{0x81, 0x3b}, // 0
{0x82, 0x3b}, // 0 : uyvy <20>ڰ<EFBFBD>
{0x83, 0x4b},
{0x84, 0x90},
{0x86, 0xf0},
{0x87, 0x1d},
{0x88, 0x16},
{0x8d, 0x74},
{0x8e, 0x25},
/*AEC*/
{0x90, 0x36},
{0x92, 0x43},
{0x9d, 0x32},
{0x9e, 0x81},
{0x9f, 0xf4},
{0xa0, 0xa0},
{0xa1, 0x04},
{0xa3, 0x2d},
{0xa4, 0x01},
/*AWB*/
{0xb0, 0xc2},
{0xb1, 0x1e},
{0xb2, 0x10},
{0xb3, 0x20},
{0xb4, 0x2d},
{0xb5, 0x1b},
{0xb6, 0x2e},
{0xb8, 0x13},
{0xba, 0x60},
{0xbb, 0x62},
{0xbd, 0x78},
{0xbe, 0x55},
{0xbf, 0xa0},
{0xc4, 0xe7},
{0xc5, 0x15},
{0xc6, 0x16},
{0xc7, 0xeb},
{0xc8, 0xe4},
{0xc9, 0x16},
{0xca, 0x16},
{0xcb, 0xe9},
{0x22, 0xf8},
/*SPI*/
{0xfe, 0x02},
{0x01, 0x01},
{0x02, 0x02},
{0x03, 0x20},
{0x04, 0x20},
{0x0a, 0x00},
{0x13, 0x10},
{0x24, 0x00},
{0x28, 0x03},
{0xfe, 0x00},
/*OUTPUT*/
{0xf2, 0x03},
{0xfe, 0x00},
};
uint16_t gc6153GetRegCnt(char* regName)
{
if (strcmp(regName, "gc6153_1sdr") == 0)
{
return (sizeof(gc6153_1sdrRegInfo) / sizeof(gc6153_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,149 @@
#include "i2cGpio.h"
// We only act as I2C master
typedef enum
{
INPUT,
OUTPUT,
}pinDirection_e;
static void setSdaDirection(pinDirection_e direction)
{
GpioPinConfig_t config;
if (direction == INPUT)
{
config.pinDirection = GPIO_DIRECTION_INPUT;
config.misc.interruptConfig = GPIO_INTERRUPT_DISABLED;
GPIO_pinConfig(SDA_GPIO_INSTANCE, SDA_GPIO_PIN, &config);
}
else
{
config.pinDirection = GPIO_DIRECTION_OUTPUT;
//config.initOutput = 0;
GPIO_pinConfig(SDA_GPIO_INSTANCE, SDA_GPIO_PIN, &config);
}
}
void i2cStart()
{
I2C_SDA_1;
I2C_SCL_1;
delay_us(20);
I2C_SDA_0;
delay_us(19);
I2C_SCL_0;
}
void i2cStop()
{
setSdaDirection(OUTPUT);
I2C_SDA_0;
I2C_SCL_1;
delay_us(18);
I2C_SDA_1;
delay_us(18);
}
static uint32_t i2cSdaRead()
{
return (((((GPIO_TypeDef *) (MP_GPIO_BASE_ADDR + 0x1000*SDA_GPIO_INSTANCE))->DATA) >> SDA_GPIO_PIN) & 0x01);
}
void i2cWritebyte(uint8_t byte)
{
setSdaDirection(OUTPUT);
for (uint8_t i=0; i<8; i++)
{
I2C_SCL_0;
delay_us(18);
// Send data every bit
if (byte&0x80)
{
I2C_SDA_1;
}
else
{
I2C_SDA_0;
}
byte <<= 1;
I2C_SCL_1;
delay_us(18);
}
I2C_SCL_0;
delay_us(18);
I2C_SDA_1;
delay_us(18);
}
void i2cAck()
{
uint8_t i = 0;
setSdaDirection(INPUT);
I2C_SCL_1;
delay_us(18);
while ((i2cSdaRead()==1) && (i<255))
i++;
I2C_SCL_0;
delay_us(18);
setSdaDirection(OUTPUT);
}
uint8_t i2cReadByte()
{
uint8_t i, receveData = 0;
setSdaDirection(INPUT);
delay_us(18);
for (i = 0; i < 8; i++)
{
I2C_SCL_1;
delay_us(18);
receveData |= (i2cSdaRead() << (7-i));
I2C_SCL_0;
delay_us(18);
}
setSdaDirection(OUTPUT);
return receveData;
}
void i2cGpioInit()
{
PadConfig_t config;
PAD_getDefaultConfig(&config);
// scl pin
config.mux = SCL_PAD_ALT_FUNC;
PAD_setPinConfig(SCL_GPIO_ADDR, &config);
GpioPinConfig_t gpioCfg;
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
gpioCfg.misc.initOutput= 1;
GPIO_pinConfig(SCL_GPIO_INSTANCE, SCL_GPIO_PIN, &gpioCfg);
// sda pin
config.mux = SDA_PAD_ALT_FUNC;
PAD_setPinConfig(SDA_GPIO_ADDR, &config);
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
gpioCfg.misc.initOutput= 1;
GPIO_pinConfig(SDA_GPIO_INSTANCE, SDA_GPIO_PIN, &gpioCfg);
}

View File

@@ -0,0 +1,349 @@
#include "cameraDrv.h"
camI2cCfg_t sp0821_2sdrRegInfo[] =
{
{0x30,0x01},
{0x32,0x00},
{0x03,0x00},
{0x04,0x96},
{0x24,0x13},
{0x9b,0x32},
{0xd7,0x00},
{0xc5,0xc7},
{0xc6,0xe2},
{0xe7,0x03},
{0x32,0x00},
{0x32,0x01},
{0x32,0x00},
{0xbf,0x0f},
{0xba,0x5a},
{0xbb,0x69},
{0xe7,0x00},
{0x32,0x07},
{0x31,0x03},
{0x19,0x04},
{0x2c,0x0f},
{0x2e,0x3c},
{0x30,0x01},
{0x28,0x2e},
{0x29,0x1f},
{0x0f,0x30},
{0x14,0xb0},
{0x38,0x50},
{0x39,0x52},
{0x3a,0x60},
{0x3b,0x10},
{0x3c,0xe0},
{0x85,0x01},
{0xe0,0x02},
{0xe5,0x60},
{0xf5,0x02},
{0xf1,0x03},
{0xf3,0x40},
{0x41,0x00},
{0x05,0x00},
{0x06,0x00},
{0x07,0x00},
{0x08,0x00},
{0x09,0x00},
{0x0a,0x34},
{0x0D,0x01},
{0xc8,0x10},
{0x29,0x1e},
{0xa2,0x26},
{0xa3,0x02},
{0xa4,0x32},
{0xa5,0x00},
{0xa8,0x32},
{0xa9,0x00},
{0xaa,0x01},
{0xab,0x00},
{0x4c,0x80},
{0x4d,0x80},
{0xa6,0xf0},
{0xa7,0x20},
{0xac,0xf0},
{0xad,0x20},
{0x8a,0x3e},
{0x8b,0x30},
{0x8c,0x2a},
{0x8d,0x26},
{0x8e,0x26},
{0x8f,0x24},
{0x90,0x24},
{0x91,0x22},
{0x92,0x22},
{0x93,0x22},
{0x94,0x20},
{0x95,0x20},
{0x96,0x20},
{0x17,0x88},
{0x18,0x80},
{0x4e,0x78},
{0x4f,0x78},
{0x58,0x8a},
{0x59,0xa8},
{0x5a,0x80},
{0xca,0x00},
{0x86,0x08},
{0x87,0x0f},
{0x88,0x30},
{0x89,0x45},
{0x9e,0x94},
{0x9f,0x88},
{0x97,0x84},
{0x98,0x88},
{0x99,0x74},
{0x9a,0x84},
{0xa0,0x7c},
{0xa1,0x78},
{0x9d,0x09},
{0xB1,0x04},
{0xb3,0x00},
{0x47,0x40},
{0xb8,0x04},
{0xb9,0x28},
{0x3f,0x18},
{0xc1,0xff},
{0xc2,0x40},
{0xc3,0xff},
{0xc4,0x40},
{0xc5,0xc7},
{0xc6,0xe2},
{0xc7,0xef},
{0xc8,0x10},
{0x50,0x2a},
{0x51,0x2a},
{0x52,0x2f},
{0x53,0xcf},
{0x54,0xd0},
{0x5c,0x1e},
{0x5d,0x21},
{0x5e,0x1a},
{0x5f,0xe9},
{0x60,0x98},
{0xcb,0x3f},
{0xcc,0x3f},
{0xcd,0x3f},
{0xce,0x85},
{0xcf,0xff},
{0x79,0x5a},
{0x7a,0xDC},
{0x7b,0x0A},
{0x7c,0xFD},
{0x7d,0x46},
{0x7e,0xFD},
{0x7f,0xFD},
{0x80,0xEF},
{0x81,0x54},
{0x1b,0x0a},
{0x1c,0x0f},
{0x1d,0x15},
{0x1e,0x15},
{0x1f,0x15},
{0x20,0x1f},
{0x21,0x2a},
{0x22,0x2a},
{0x56,0x49},
{0x1a,0x14},
{0x34,0x1f},
{0x82,0x10},
{0x83,0x00},
{0x84,0xff},
{0xd7,0x50},
{0xd8,0x1a},
{0xd9,0x20},
{0xc9,0x1f},
{0xbf,0x33},
{0xba,0x37},
{0xbb,0x38},
{0x19,0x04},
{0x34,0x1f},
{0x30,0x01},
{0x2e,0x2c},//0x29
{0x2c,0x0f},
};
camI2cCfg_t sp0821_1sdrRegInfo[] =
{
{0x30,0x01},
{0x32,0x00},
{0x03,0x00},
{0x04,0x96},
{0x24,0x13},
{0x9b,0x32},
{0xd7,0x00},
{0xc5,0xc7},
{0xc6,0xe2},
{0xe7,0x03},
{0x32,0x00},
{0x32,0x01},
{0x32,0x00},
{0xbf,0x0f},
{0xba,0x5a},
{0xbb,0x69},
{0xe7,0x00},
{0x32,0x07},
{0x31,0x03},
{0x19,0x04},
{0x2c,0x0f},
{0x2e,0x3c},
{0x30,0x01},
{0x28,0x2e},
{0x29,0x1f},
{0x0f,0x30},
{0x14,0xb0},
{0x38,0x50},
{0x39,0x52},
{0x3a,0x60},
{0x3b,0x10},
{0x3c,0xe0},
{0x85,0x01},
{0xe0,0x02},
{0xe5,0x60},
{0xf5,0x02},
{0xf1,0x03},
{0xf3,0x40},
{0x41,0x00},
{0x05,0x00},
{0x06,0x00},
{0x07,0x00},
{0x08,0x00},
{0x09,0x00},
{0x0a,0x34},
{0x0D,0x01},
{0xc8,0x10},
{0x29,0x1e},
{0xa2,0x26},
{0xa3,0x02},
{0xa4,0x32},
{0xa5,0x00},
{0xa8,0x32},
{0xa9,0x00},
{0xaa,0x01},
{0xab,0x00},
{0x4c,0x80},
{0x4d,0x80},
{0xa6,0xf0},
{0xa7,0x20},
{0xac,0xf0},
{0xad,0x20},
{0x8a,0x3e},
{0x8b,0x30},
{0x8c,0x2a},
{0x8d,0x26},
{0x8e,0x26},
{0x8f,0x24},
{0x90,0x24},
{0x91,0x22},
{0x92,0x22},
{0x93,0x22},
{0x94,0x20},
{0x95,0x20},
{0x96,0x20},
{0x17,0x88},
{0x18,0x80},
{0x4e,0x78},
{0x4f,0x78},
{0x58,0x8a},
{0x59,0xa8},
{0x5a,0x80},
{0xca,0x00},
{0x86,0x08},
{0x87,0x0f},
{0x88,0x30},
{0x89,0x45},
{0x9e,0x94},
{0x9f,0x88},
{0x97,0x84},
{0x98,0x88},
{0x99,0x74},
{0x9a,0x84},
{0xa0,0x7c},
{0xa1,0x78},
{0x9d,0x09},
{0xB1,0x04},
{0xb3,0x00},
{0x47,0x40},
{0xb8,0x04},
{0xb9,0x28},
{0x3f,0x18},
{0xc1,0xff},
{0xc2,0x40},
{0xc3,0xff},
{0xc4,0x40},
{0xc5,0xc7},
{0xc6,0xe2},
{0xc7,0xef},
{0xc8,0x10},
{0x50,0x2a},
{0x51,0x2a},
{0x52,0x2f},
{0x53,0xcf},
{0x54,0xd0},
{0x5c,0x1e},
{0x5d,0x21},
{0x5e,0x1a},
{0x5f,0xe9},
{0x60,0x98},
{0xcb,0x3f},
{0xcc,0x3f},
{0xcd,0x3f},
{0xce,0x85},
{0xcf,0xff},
{0x79,0x5a},
{0x7a,0xDC},
{0x7b,0x0A},
{0x7c,0xFD},
{0x7d,0x46},
{0x7e,0xFD},
{0x7f,0xFD},
{0x80,0xEF},
{0x81,0x54},
{0x1b,0x0a},
{0x1c,0x0f},
{0x1d,0x15},
{0x1e,0x15},
{0x1f,0x15},
{0x20,0x1f},
{0x21,0x2a},
{0x22,0x2a},
{0x56,0x49},
{0x1a,0x14},
{0x34,0x1f},
{0x82,0x10},
{0x83,0x00},
{0x84,0xff},
{0xd7,0x50},
{0xd8,0x1a},
{0xd9,0x20},
{0xc9,0x1f},
{0xbf,0x33},
{0xba,0x37},
{0xbb,0x38},
{0x19,0x04},
{0x34,0x1f},
{0x30,0x01},
{0x2e,0x2c},//0x29
{0x2c,0x0f},
};
uint16_t sp0821GetRegCnt(char* regName)
{
if (strcmp(regName, "sp0821_2sdr") == 0)
{
return (sizeof(sp0821_2sdrRegInfo) / sizeof(sp0821_2sdrRegInfo[0]));
}
else if (strcmp(regName, "sp0821_1sdr") == 0)
{
return (sizeof(sp0821_1sdrRegInfo) / sizeof(sp0821_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,740 @@
#include "cameraDrv.h"
camI2cCfg_t sp0A39_2sdrRegInfo[] =
{
{0xfd,0x00},
{0x1d,0x25},
{0x31,0x04},
{0x32,0x01},
{0x30,0x01},
{0xfd,0x01},
{0x5d,0x01},
{0x34,0xe3},
{0x35,0x10},
{0xfd,0x00},
{0xf0,0xff},
{0xf1,0xff},
{0xf2,0xff},
{0xf3,0xff},
{0xfc,0x50},
{0xfd,0x00},
{0x03,0x00},
{0x04,0xf0},
{0x24,0x10},
{0xef,0x40},
{0x06,0x00},
{0x09,0x00},
{0x0a,0x46},
{0x10,0x07},
{0x11,0x04},
{0x16,0x01},
{0x19,0x22},
{0x1e,0x58},
{0x29,0x48},
{0x13,0x37},
{0x14,0x01},
{0x25,0x01},
{0x2a,0x06},
{0x27,0x01},
{0x54,0x00},
{0x55,0x10},
{0x58,0x38},
{0x5d,0x12},
{0x63,0x00},
{0x64,0x00},
{0x66,0x28},
{0x68,0x2a},
{0x72,0x3a},
{0x73,0x0a},
{0x75,0x48},
{0x76,0x0a},
{0x1f,0x77},
{0x20,0x07},
{0xfb,0x16},
{0xfd,0x01},
{0xf2,0x69},
{0xf7,0x28},
{0x02,0x10},
{0x03,0x01},
{0x06,0x28},
{0x08,0x01},
{0xfd,0x02},
{0xb8,0x50},
{0xb9,0xff},
{0xba,0x40},
{0xbb,0x45},
{0xbc,0xc0},
{0xbd,0x50},
{0xbe,0x80},
{0xbf,0x02},
{0xd0,0x80},
{0xd1,0x02},
{0xfd,0x01},
{0xc0,0x1f},
{0xc1,0x18},
{0xc2,0x15},
{0xc3,0x13},
{0xc4,0x13},
{0xc5,0x12},
{0xc6,0x12},
{0xc7,0x11},
{0xc8,0x11},
{0xc9,0x11},
{0xca,0x10},
{0xf3,0x10},
{0xf4,0x10},
{0xfd,0x01},
{0x04,0xff},
{0x05,0x10},
{0x0a,0x30},
{0x0b,0x10},
{0xfd,0x01},
{0xcb,0x38},
{0xcc,0x35},
{0xcd,0x03},
{0xce,0x05},
{0xfd,0x00},
{0xfb,0x16},
{0x35,0xaa},
{0xfd,0x01},
{0x1e,0x00},
{0x20,0x00},
{0x84,0x25},
{0x85,0x25},
{0x86,0x1f},
{0x87,0x23},
{0x88,0x1c},
{0x89,0x20},
{0x8a,0x1a},
{0x8b,0x15},
{0x8c,0x15},
{0x8d,0x1a},
{0x8e,0x0a},
{0x8f,0x13},
{0x90,0x13},
{0x91,0x00},
{0x92,0x0a},
{0x93,0x08},
{0x94,0x12},
{0x95,0x00},
{0x96,0x0a},
{0x97,0x08},
{0x98,0x15},
{0x99,0x00},
{0x9a,0x0a},
{0x9b,0x05},
{0xe8,0x20},
{0xe9,0x0f},
{0xea,0x00},
{0xfd,0x01},
{0xa4,0x00},
{0x0e,0x80},
{0x18,0x80},
{0x0f,0x20},
{0x10,0x90},
{0x11,0x80},
{0x12,0x80},
{0x13,0xa0},
{0x14,0x80},
{0x15,0x90},
{0x16,0x85},
{0x17,0x85},
{0x6e,0x00},
{0x6f,0x03},
{0x70,0x07},
{0x71,0x0d},
{0x72,0x17},
{0x73,0x29},
{0x74,0x3d},
{0x75,0x4f},
{0x76,0x5f},
{0x77,0x79},
{0x78,0x8c},
{0x79,0x9d},
{0x7a,0xa9},
{0x7b,0xb3},
{0x7c,0xbe},
{0x7d,0xc7},
{0x7e,0xd0},
{0x7f,0xd6},
{0x80,0xde},
{0x81,0xe4},
{0x82,0xe9},
{0x83,0xee},
{0xfd,0x02},
{0x09,0x06},
{0x0d,0x1a},
{0x1c,0x09},
{0x1d,0x03},
{0x1e,0x10},
{0x1f,0x06},
{0xfd,0x01},
{0x32,0x00},
{0xfd,0x02},
{0x26,0xcb},
{0x27,0xc2},
{0x10,0x00},
{0x11,0x00},
{0x18,0x17},
{0x19,0x36},
{0x2a,0x01},
{0x2b,0x10},
{0x28,0xf8},
{0x29,0x08},
{0x66,0x5F},
{0x67,0x7f},
{0x68,0xE0},
{0x69,0x10},
{0x69,0x10},
{0x6a,0xa6},
{0x7c,0x4A},
{0x7d,0x80},
{0x7e,0x00},
{0x7f,0x30},
{0x80,0xaa},
{0x70,0x32},
{0x71,0x60},
{0x72,0x30},
{0x73,0x5a},
{0x74,0xaa},
{0x6b,0xff},
{0x6c,0x50},
{0x6d,0x40},
{0x6e,0x60},
{0x6f,0x6a},
{0x61,0xff},
{0x62,0x27},
{0x63,0x51},
{0x64,0x7f},
{0x65,0x6a},
{0x75,0x80},
{0x76,0x09},
{0x77,0x02},
{0x0e,0x12},
{0x3b,0x09},
{0x48,0xea},
{0x49,0xfc},
{0x4a,0x05},
{0x02,0x00},
{0x03,0x88},
{0xf5,0xfe},
{0x22,0xfe},
{0x20,0xfe},
{0xf7,0xfe},
{0xfd,0x02},
{0xde,0x0f},
{0xcf,0x0a},
{0xd7,0x0a},
{0xd8,0x12},
{0xd9,0x14},
{0xda,0x1a},
{0xdc,0x07},
{0xe8,0x60},
{0xe9,0x40},
{0xea,0x40},
{0xeb,0x30},
{0xec,0x60},
{0xed,0x50},
{0xee,0x40},
{0xef,0x30},
{0xd3,0x30},
{0xd4,0xc0},
{0xd5,0x50},
{0xd6,0x0b},
{0xf0,0x7f},
{0xfd,0x01},
{0xb1,0xf0},
{0xfd,0x02},
{0xdc,0x07},
{0x05,0x08},
{0xfd,0x01},
{0x26,0x33},
{0x27,0x99},
{0x62,0xf0},
{0x63,0x80},
{0x64,0x80},
{0x65,0x20},
{0xfd,0x02},
{0xdd,0xff},
{0xfd,0x01},
{0xa8,0x00},
{0xa9,0x09},
{0xaa,0x09},
{0xab,0x0c},
{0xd3,0x00},
{0xd4,0x09},
{0xd5,0x09},
{0xd6,0x0c},
{0xcf,0xff},
{0xd0,0xf0},
{0xd1,0x80},
{0xd2,0x80},
{0xdf,0xff},
{0xe0,0xf0},
{0xe1,0xd0},
{0xe2,0x80},
{0xe3,0xff},
{0xe4,0xf0},
{0xe5,0xd0},
{0xe6,0x80},
{0xfd,0x02},
{0x15,0xe0},
{0x16,0x95},
{0xa0,0x9b},
{0xa1,0xe4},
{0xa2,0x01},
{0xa3,0xf2},
{0xa4,0x8f},
{0xa5,0xff},
{0xa6,0x01},
{0xa7,0xdb},
{0xa8,0xa4},
{0xac,0x80},
{0xad,0x21},
{0xae,0xdf},
{0xaf,0xf2},
{0xb0,0xa0},
{0xb1,0xee},
{0xb2,0xea},
{0xb3,0xd9},
{0xb4,0xbd},
{0xfd,0x01},
{0xb3,0xb0},
{0xb4,0x90},
{0xb5,0x70},
{0xb6,0x55},
{0xb7,0xb0},
{0xb8,0x90},
{0xb9,0x70},
{0xba,0x55},
{0xfd,0x01},
{0xbf,0xff},
{0x00,0x00},
{0xfd,0x01},
{0xa4,0x00},
{0xa5,0x1f},
{0xa6,0x50},
{0xa7,0x65},
{0xfd,0x02},
{0x30,0x38},
{0x31,0x40},
{0x32,0x40},
{0x33,0xd0},
{0x34,0x10},
{0x35,0x60},
{0x36,0x28},
{0x37,0x07},
{0x38,0x08},
{0xe6,0x8F},
{0xfd,0x01},
{0x1b,0x15},
{0x1c,0x1A},
{0x1d,0x0c},
{0xfd,0x01},
{0x32,0x15},
{0x33,0xef},
{0x36,0x10},
{0xf6,0xb0},
{0xf5,0x10},
{0xd7,0x3a},
{0xd8,0x10},
{0xd9,0x20},
{0xda,0x10},
{0xdb,0x7a},
{0xdc,0x3a},
{0xdd,0x30},
{0xde,0x30},
{0xe7,0x3a},
{0x9c,0xaa},
{0x9d,0xaa},
{0x9e,0x55},
{0x9f,0x55},
{0xfd,0x00},
{0x1c,0x00},
{0xfd,0x00},
{0xfd,0x00},
{0x30,0x0b},
{0x1c,0xdc},
{0x2c,0x1d}, // LSB
{0x2e,0xe1},
};
camI2cCfg_t sp0A39_1sdrRegInfo[] =
{
{0xfd,0x00},
{0x1d,0x25},
{0x31,0x04},
{0x32,0x01},
{0x30,0x01},
{0xfd,0x01},
{0x5d,0x01},
{0x34,0xe3},
{0x35,0x10},
{0xfd,0x00},
{0xf0,0xff},
{0xf1,0xff},
{0xf2,0xff},
{0xf3,0xff},
{0xfc,0x50},
{0xfd,0x00},
{0x03,0x03},
{0x04,0x6c},
{0x24,0x10},
{0xef,0x40},
{0x06,0x00},
{0x09,0x00},
{0x0a,0x80},
{0x10,0x07},
{0x11,0x04},
{0x16,0x01},
{0x19,0x22},
{0x1e,0x58},
{0x29,0x48},
{0x13,0x37},
{0x14,0x01},
{0x25,0x01},
{0x2a,0x06},
{0x27,0x01},
{0x54,0x00},
{0x55,0x10},
{0x58,0x38},
{0x5d,0x12},
{0x63,0x00},
{0x64,0x00},
{0x66,0x28},
{0x68,0x2a},
{0x72,0x3a},
{0x73,0x0a},
{0x75,0x48},
{0x76,0x0a},
{0x1f,0x77},
{0x20,0x07},
{0xfb,0x16},
{0xfd,0x01},
{0xf2,0x69},
{0xf7,0x97},
{0x02,0x08},
{0x03,0x01},
{0x06,0x8a},
{0x08,0x01},
{0xfd,0x02},
{0xb8,0x50},
{0xb9,0xff},
{0xba,0x40},
{0xbb,0x45},
{0xbc,0xc0},
{0xbd,0x50},
{0xbe,0xb8},
{0xbf,0x04},
{0xd0,0xb8},
{0xd1,0x04},
{0xfd,0x01},
{0xc0,0x1f},
{0xc1,0x18},
{0xc2,0x15},
{0xc3,0x13},
{0xc4,0x13},
{0xc5,0x12},
{0xc6,0x12},
{0xc7,0x11},
{0xc8,0x11},
{0xc9,0x11},
{0xca,0x10},
{0xf3,0x10},
{0xf4,0x10},
{0xfd,0x01},
{0x04,0xff},
{0x05,0x10},
{0x0a,0x30},
{0x0b,0x10},
{0xfd,0x01},
{0xcb,0x38},
{0xcc,0x35},
{0xcd,0x03},
{0xce,0x05},
{0xfd,0x00},
{0xfb,0x16},
{0x35,0xaa},
{0xfd,0x01},
{0x1e,0x00},
{0x20,0x00},
{0x84,0x25},
{0x85,0x25},
{0x86,0x1f},
{0x87,0x23},
{0x88,0x1c},
{0x89,0x20},
{0x8a,0x1a},
{0x8b,0x15},
{0x8c,0x15},
{0x8d,0x1a},
{0x8e,0x0a},
{0x8f,0x13},
{0x90,0x13},
{0x91,0x00},
{0x92,0x0a},
{0x93,0x08},
{0x94,0x12},
{0x95,0x00},
{0x96,0x0a},
{0x97,0x08},
{0x98,0x15},
{0x99,0x00},
{0x9a,0x0a},
{0x9b,0x05},
{0xe8,0x20},
{0xe9,0x0f},
{0xea,0x00},
{0xfd,0x01},
{0xa4,0x00},
{0x0e,0x80},
{0x18,0x80},
{0x0f,0x20},
{0x10,0x90},
{0x11,0x80},
{0x12,0x80},
{0x13,0xa0},
{0x14,0x80},
{0x15,0x90},
{0x16,0x85},
{0x17,0x85},
{0x6e,0x00},
{0x6f,0x03},
{0x70,0x07},
{0x71,0x0d},
{0x72,0x17},
{0x73,0x29},
{0x74,0x3d},
{0x75,0x4f},
{0x76,0x5f},
{0x77,0x79},
{0x78,0x8c},
{0x79,0x9d},
{0x7a,0xa9},
{0x7b,0xb3},
{0x7c,0xbe},
{0x7d,0xc7},
{0x7e,0xd0},
{0x7f,0xd6},
{0x80,0xde},
{0x81,0xe4},
{0x82,0xe9},
{0x83,0xee},
{0xfd,0x02},
{0x09,0x06},
{0x0d,0x1a},
{0x1c,0x09},
{0x1d,0x03},
{0x1e,0x10},
{0x1f,0x06},
{0xfd,0x01},
{0x32,0x00},
{0xfd,0x02},
{0x26,0xcb},
{0x27,0xc2},
{0x10,0x00},
{0x11,0x00},
{0x18,0x17},
{0x19,0x36},
{0x2a,0x01},
{0x2b,0x10},
{0x28,0xf8},
{0x29,0x08},
{0x66,0x5F},
{0x67,0x7f},
{0x68,0xE0},
{0x69,0x10},
{0x69,0x10},
{0x6a,0xa6},
{0x7c,0x4A},
{0x7d,0x80},
{0x7e,0x00},
{0x7f,0x30},
{0x80,0xaa},
{0x70,0x32},
{0x71,0x60},
{0x72,0x30},
{0x73,0x5a},
{0x74,0xaa},
{0x6b,0xff},
{0x6c,0x50},
{0x6d,0x40},
{0x6e,0x60},
{0x6f,0x6a},
{0x61,0xff},
{0x62,0x27},
{0x63,0x51},
{0x64,0x7f},
{0x65,0x6a},
{0x75,0x80},
{0x76,0x09},
{0x77,0x02},
{0x0e,0x12},
{0x3b,0x09},
{0x48,0xea},
{0x49,0xfc},
{0x4a,0x05},
{0x02,0x00},
{0x03,0x88},
{0xf5,0xfe},
{0x22,0xfe},
{0x20,0xfe},
{0xf7,0xfe},
{0xfd,0x02},
{0xde,0x0f},
{0xcf,0x0a},
{0xd7,0x0a},
{0xd8,0x12},
{0xd9,0x14},
{0xda,0x1a},
{0xdc,0x07},
{0xe8,0x60},
{0xe9,0x40},
{0xea,0x40},
{0xeb,0x30},
{0xec,0x60},
{0xed,0x50},
{0xee,0x40},
{0xef,0x30},
{0xd3,0x30},
{0xd4,0xc0},
{0xd5,0x50},
{0xd6,0x0b},
{0xf0,0x7f},
{0xfd,0x01},
{0xb1,0xf0},
{0xfd,0x02},
{0xdc,0x07},
{0x05,0x08},
{0xfd,0x01},
{0x26,0x33},
{0x27,0x99},
{0x62,0xf0},
{0x63,0x80},
{0x64,0x80},
{0x65,0x20},
{0xfd,0x02},
{0xdd,0xff},
{0xfd,0x01},
{0xa8,0x00},
{0xa9,0x09},
{0xaa,0x09},
{0xab,0x0c},
{0xd3,0x00},
{0xd4,0x09},
{0xd5,0x09},
{0xd6,0x0c},
{0xcf,0xff},
{0xd0,0xf0},
{0xd1,0x80},
{0xd2,0x80},
{0xdf,0xff},
{0xe0,0xf0},
{0xe1,0xd0},
{0xe2,0x80},
{0xe3,0xff},
{0xe4,0xf0},
{0xe5,0xd0},
{0xe6,0x80},
{0xfd,0x02},
{0x15,0xe0},
{0x16,0x95},
{0xa0,0x9b},
{0xa1,0xe4},
{0xa2,0x01},
{0xa3,0xf2},
{0xa4,0x8f},
{0xa5,0xff},
{0xa6,0x01},
{0xa7,0xdb},
{0xa8,0xa4},
{0xac,0x80},
{0xad,0x21},
{0xae,0xdf},
{0xaf,0xf2},
{0xb0,0xa0},
{0xb1,0xee},
{0xb2,0xea},
{0xb3,0xd9},
{0xb4,0xbd},
{0xfd,0x01},
{0xb3,0xb0},
{0xb4,0x90},
{0xb5,0x70},
{0xb6,0x55},
{0xb7,0xb0},
{0xb8,0x90},
{0xb9,0x70},
{0xba,0x55},
{0xfd,0x01},
{0xbf,0xff},
{0x00,0x00},
{0xfd,0x01},
{0xa4,0x00},
{0xa5,0x1f},
{0xa6,0x50},
{0xa7,0x65},
{0xfd,0x02},
{0x30,0x38},
{0x31,0x40},
{0x32,0x40},
{0x33,0xd0},
{0x34,0x10},
{0x35,0x60},
{0x36,0x28},
{0x37,0x07},
{0x38,0x08},
{0xe6,0x8F},
{0xfd,0x01},
{0x1b,0x15},
{0x1c,0x1A},
{0x1d,0x0c},
{0xfd,0x01},
{0x32,0x15},
{0x33,0xef},
{0x36,0x10},
{0xf6,0xb0},
{0xf5,0x10},
{0xd7,0x3a},
{0xd8,0x10},
{0xd9,0x20},
{0xda,0x10},
{0xdb,0x7a},
{0xdc,0x3a},
{0xdd,0x30},
{0xde,0x30},
{0xe7,0x3a},
{0x9c,0xaa},
{0x9d,0xaa},
{0x9e,0x55},
{0x9f,0x55},
{0xfd,0x00},
{0x1c,0x00},
{0xfd,0x00},
{0xfd,0x00},
{0x30,0x0c},
{0x1c,0xde},
{0x2c,0x1d}, //LSB
//{0x2c,0x15}, //MSB
{0x2e,0xf0},
};
uint16_t sp0a39GetRegCnt(char* regName)
{
if (strcmp(regName, "sp0a39_2sdr") == 0)
{
return (sizeof(sp0A39_2sdrRegInfo) / sizeof(sp0A39_2sdrRegInfo[0]));
}
else if (strcmp(regName, "sp0a39_1sdr") == 0)
{
return (sizeof(sp0A39_1sdrRegInfo) / sizeof(sp0A39_1sdrRegInfo[0]));
}
return 0;
}

View File

@@ -0,0 +1,315 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: eepRom.c
* Description: EC618 eepRom ds2431 driver source file
* History: Rev1.0 2020-12-17
*
****************************************************************************/
#include "ec618.h"
#include "bsp.h"
#include "eepRom.h"
#include "oneWire.h"
#include "string.h"
#include "stdio.h"
extern void delay_us(uint32_t us);
static uint16_t crc16Maxim(uint8_t *data, uint16_t len)
{
uint8_t i;
uint16_t crc = 0;
while (len--)
{
crc ^= *data++;
for (i=0; i<8; ++i)
{
if (crc&1)
{
crc = (crc>>1) ^ 0xA001;
}
else
{
crc = crc>>1;
}
}
}
return ~crc;
}
int32_t writeScratchpad(uint8_t addr, uint8_t data[8])
{
uint8_t crcSrcData[11];
uint16_t crcCalResult;
uint8_t crcReadData[2];
if ((data == NULL) || (addr > 0x8F))
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
if (owResetPd() != 0)
{
return EEPROMDRV_RESET_ERR;
}
delay_us(140); // delay 200us
owWriteByte(ROM_SKIP_CMD);
owWriteByte(SCRATCHPAD_WRITE_CMD);
owWriteByte(addr);
owWriteByte(0x00);
crcSrcData[0] = SCRATCHPAD_WRITE_CMD; // before are right
crcSrcData[1] = addr;
crcSrcData[2] = 0x00;
for (int i=0; i<8; i++)
{
owWriteByte(data[i]);
crcSrcData[i+3] = data[i];
}
crcCalResult = crc16Maxim(crcSrcData, 11); // before are right
owReadByte(crcReadData);
owReadByte(crcReadData+1);
if (((crcReadData[1]<<8) | crcReadData[0]) != crcCalResult)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
return EEPROMDRV_OK;
}
void readScratchpad(uint8_t dataBack[13])
{
if (owResetPd() != 0)
{
return;
}
delay_us(140); // delay 200us
owWriteByte(ROM_SKIP_CMD);
owWriteByte(SCRATCHPAD_READ_CMD);
// first 3 bytes are: TA1, TA2, ES; Then 8 bytes data; Last are 2 bytes crc
for (int i=0; i<13; i++)
{
owReadByte(dataBack+i);
}
}
int32_t copyScratchpad2Mem(uint16_t addr)
{
uint8_t readData;
if (owResetPd() != 0)
{
return EEPROMDRV_RESET_ERR;
}
delay_us(140); // delay 200us
owWriteByte(ROM_SKIP_CMD);
owWriteByte(SCRATCHPAD_COPY_CMD);
owWriteByte(addr);
owWriteByte(0x00);
owWriteByte(0x07);
delay_us(140); // delay 200us
owReadByte(&readData);
if (readData != 0xAA)
{
return EEPROMDRV_SCRATCHPADCOPY_ERR;
}
return EEPROMDRV_OK;
}
uint8_t dataBack[13]={0};
int32_t dataCmp(uint8_t targetAddr, uint8_t* buffer, uint8_t len)
{
// compare the data read from scratchpad
if (dataBack[0] != targetAddr)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
if (dataBack[1] != 0)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
if (dataBack[2] != 0x7)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
for (int j=0; j<len; j++)
{
if (dataBack[j+3] != buffer[j])
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
}
return EEPROMDRV_OK;
}
int32_t eePromReadRom(uint8_t* romCode)
{
if (owResetPd() !=0)
{
return EEPROMDRV_RESET_ERR;
}
delay_us(140); // delay 200us
#if 0
uint8_t data = ROM_READ_CMD;
int i;
for (i=0; i<8; i++)
{
owWriteBit(data&0x01);
data >>=1;
}
uint8_t dataRead;
for (i=0; i<8; i++)
{
owReadBit(&dataRead);
dataRead <<=1;
}
#endif
#if 1
int32_t result = owWriteByte(ROM_READ_CMD);
if (result < 0)
{
return EEPROMDRV_ROMREAD_ERR;
}
for (int32_t i=0; i<8; i++)
{
owReadByte(romCode+i);
}
#endif
return EEPROMDRV_OK;
}
int32_t eePromReadMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer)
{
delay_us(3000); // wait unitl former write operations finish
if (owResetPd() != 0)
{
return EEPROMDRV_RESET_ERR;
}
delay_us(140); // delay 200us
if (owWriteByte(ROM_SKIP_CMD) < 0)
{
return EEPROMDRV_ROMREAD_ERR;
}
if (owWriteByte(MEM_READ_CMD) < 0)
{
return EEPROMDRV_ROMREAD_ERR;
}
// write addr low byte
if (owWriteByte(targetAddr) < 0)
{
return EEPROMDRV_ROMREAD_ERR;
}
// write addr high byte
if (owWriteByte(0) < 0)
{
return EEPROMDRV_ROMREAD_ERR;
}
for (int i=0; i<len; i++)
{
owReadByte(buffer+i);
}
return owResetPd();
}
int32_t writeSctStats;
int32_t eePromWriteMem(uint8_t targetAddr, uint8_t len, uint8_t* buffer)
{
uint8_t tmp[8];
int i, index=0;
if (owResetPd() != 0)
{
return EEPROMDRV_RESET_ERR;
}
if (targetAddr > 0x88)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
while (len > 8)
{
for (i=0; i<8; i++)
{
tmp[i] = buffer[i+index];
}
len -= 8;
writeSctStats = writeScratchpad(targetAddr+index, tmp);
delay_us(3000);
readScratchpad(dataBack);
if (dataCmp(targetAddr+index, buffer+index, 8) != 0)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
copyScratchpad2Mem(targetAddr+index);
delay_us(3000);
memset(dataBack, 0, 13);
index += 8;
}
for (i=0; i<len; i++)
{
tmp[i] = buffer[i+index];
}
memset(tmp+i, 1, 8-len);
delay_us(3000); // wait until eeprom store data finish
writeSctStats = writeScratchpad(targetAddr+index, tmp);
delay_us(3000);
readScratchpad(dataBack);
if (dataCmp(targetAddr+index, buffer+index, len) != 0)
{
return EEPROMDRV_SCRATCHPADWRITE_ERR;
}
copyScratchpad2Mem(targetAddr+index);
delay_us(30000); // wait until eeprom store data finish
if (owResetPd() != 0)
{
return EEPROMDRV_RESET_ERR;
}
return EEPROMDRV_OK;
}
void eepRomInit(OwModeSel_e mode)
{
owInit();
owSetMode(mode);
}

View File

@@ -0,0 +1,281 @@
#include "imageProcess.h"
/* This file is used for camera preview. Since LCD will have different resolution, and decoder library need
a fixed resolution, so the picture from camera needs to be processed to fit different LCD resolution. */
/**
\brief Scale the picture. Now this api can only zoom out the picture.
\param[in] ratio Zoom out ratio.
\param[in] inPtr Data source.
\param[in] width Source data width.
\param[in] height Source data height.
\param[out] outPtr Output data address.
\return
*/
void scalePic(uint8_t ratio, uint8_t* inPtr, uint16_t width, uint16_t height, uint8_t *outPtr)
{
uint8_t *p = outPtr;
uint16_t h, w;
for (h = 0; h < height; h += ratio)
{
for (w = 0; w < width; w += ratio)
{
*p++ = inPtr[w + h*width];
}
}
}
/**
\brief Clockwise rotate 90 degree.
\param[in/out] mem Data source.
\param[in] width Source picture width.
\param[in] height Source picture height.
\return
*/
void imageRotate(uint8_t* mem, uint32_t width, uint32_t height)
{
uint8_t* tmpData = (uint8_t *)malloc(width * height);
memcpy(tmpData, mem, width*height);
for (int i= 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
mem[i*height + j] = tmpData[(height-1-j) * width + i];
}
}
free(tmpData);
}
/**
\brief Organize the bytes as horizontal or vertical.
\param[in] inPut Src data.
\param[in] pageLen The pageNum you want for these data, this param is set by you.
\param[in] width The width you want for these data, this param is set by you.
\param[out] outPut Output buffer.
\param[in] horizotal These data you want to array them as horizontal or vertical.
\return
*/
void storeByteIntoArray(uint8_t *inPut, uint8_t pageLen, uint16_t width, uint8_t *outPut, bool horizotal)
{
uint32_t i, j;
uint32_t index = 0;
if (horizotal)
{
for (i = 0; i < pageLen*width; i++)
{
outPut[index++] = inPut[i];
}
}
else
{
for (i = 0; i < width; i++)
{
for (j = 0; j < pageLen; j++)
{
outPut[i + j*width] = inPut[i*pageLen + j];
}
}
}
}
/**
\brief Merge 8bytes into one byte, used in 1-bit LCD.
\param[in] p Src data.
\param[out] outPut Output buffer.
\param[in] width Source data width.
\param[out] height Source data height.
\param[in] horizotal Fetch the data by row or by column.
\param[in] inByteRevert Within the byte, positive or reverse the bit sequence.
\return index How many bytes has been returned, for debug use
*/
uint16_t merge8Bytes2OneByte(uint8_t* p, uint8_t *outPut, uint16_t width, uint16_t height, bool horizotal, bool inByteRevert)
{
int i;
uint8_t data=0, data0=0, data1=0, data2=0, data3=0, data4=0, data5=0, data6=0, data7=0;
uint16_t index = 0;
if (horizotal)
{
for (i = 0 ; i < width*height; i+=8)
{
data0 = p[i];
data1 = p[i+1];
data2 = p[i+2];
data3 = p[i+3];
data4 = p[i+4];
data5 = p[i+5];
data6 = p[i+6];
data7 = p[i+7];
if (inByteRevert)
{
data = data0 | (data1<<1) | (data2<<2) | (data3<<3) | (data4<<4) | (data5<<5) | (data6<<6) | (data7<<7);
}
else
{
data = data7 | (data6<<1) | (data5<<2) | (data4<<3) | (data3<<4) | (data2<<5) | (data1<<6) | (data0<<7);
}
outPut[index++] = data;
}
}
else
{
for (uint32_t page = 0; page < height/8; page++)
{
i = page*width*8;
for (; i < page*width*8 + width; i++)
{
data0 = p[i];
data1 = p[i+1*width];
data2 = p[i+2*width];
data3 = p[i+3*width];
data4 = p[i+4*width];
data5 = p[i+5*width];
data6 = p[i+6*width];
data7 = p[i+7*width];
if (inByteRevert)
{
data = data0 | (data1<<1) | (data2<<2) | (data3<<3) | (data4<<4) | (data5<<5) | (data6<<6) | (data7<<7);
}
else
{
data = data7 | (data6<<1) | (data5<<2) | (data4<<3) | (data3<<4) | (data2<<5) | (data1<<6) | (data0<<7);
}
outPut[index++] = data;
}
}
}
return index;
}
/**
\brief Binary the source picture.
\param[in] inPut Src data.
\param[in] width Source picture width.
\param[in] height Source picture height.
\param[out] outPut Output buffer.
\return
*/
void calBinary(uint8_t* inPut, uint16_t width, uint16_t height, uint8_t* outPut)
{
uint32_t sum = 0, avg = 0, i;
for (i = 0; i < width*height; i++)
{
sum += *(inPut + i);
}
avg = sum / (width*height);
for (uint32_t j = 0; j < width*height; j++)
{
if (*(inPut + j) < avg)
{
*(outPut + j) = 1;
}
else
{
*(outPut + j) = 0;
}
}
}
/**
\brief Reverse the high 4bits and low 4bits.
\param[in/out] p source/output memory.
\param[in] num source data num.
\return
*/
void reverseByte(uint8_t* p, int num)
{
uint8_t data = 0;
for (int i = 0; i< num; i++)
{
data = *(p+i);
data = ((data&0x0f)<<4) | ((data&0xf0)>>4);
*(p+i) = data;
}
}
/**
\brief Clear low 7bits.
\param[in/out] p Src/output mem.
\param[in] num source data num.
\return
*/
void clearLow7bits(uint8_t* p, int num)
{
for (int i = 0; i < num; i++)
{
*(p+i) = *(p+i) & 0x80;
}
}
/**
\brief Convert yuv422 to rgb565, used in color screen.
\param[in] inbuf source memory.
\param[out] outbuf output memory.
\param[in] width source picture width.
\param[in] height source picture height.
\return
*/
#define RANGE_LIMIT(x) (x > 255 ? 255 : (x < 0 ? 0 : x))
void yuv422ToRgb565(const void* inbuf, void* outbuf, int width, int height)
{
int rows, cols;
int y, u, v, r, g, b;
unsigned char *yuv_buf;
unsigned short *rgb_buf;
int y_pos,u_pos,v_pos;
yuv_buf = (unsigned char *)inbuf;
rgb_buf = (unsigned short *)outbuf;
y_pos = 0;
u_pos = 1;
v_pos = 3;
for (rows = 0; rows < height; rows++)
{
for (cols = 0; cols < width; cols++)
{
y = yuv_buf[y_pos];
u = yuv_buf[u_pos] - 128;
v = yuv_buf[v_pos] - 128;
// R = Y + 1.402*(V-128)
// G = Y - 0.34414*(U-128)
// B = Y + 1.772*(U-128)
r = RANGE_LIMIT(y + v + ((v * 103) >> 8));
g = RANGE_LIMIT(y - ((u * 88) >> 8) - ((v * 183) >> 8));
b = RANGE_LIMIT(y + u + ((u * 198) >> 8));
*rgb_buf++ = (((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
y_pos += 2;
if (cols & 0x01)
{
u_pos += 4;
v_pos += 4;
}
}
}
}

View File

@@ -0,0 +1,280 @@
#include "lcdDrv.h"
extern void delay_us(uint32_t us);
int8_t lcdDmaTxCh; // dma tx channel
DmaDescriptor_t __ALIGNED(16) lcdDmaTxDesc[HEIGHT];
//uint8_t dmaTxData[WIDTH*2];
static DmaTransferConfig_t lcdDmaTxCfg =
{
NULL,
(void *)&(SPI->DR),
DMA_FLOW_CONTROL_TARGET,
DMA_ADDRESS_INCREMENT_SOURCE,
DMA_DATA_WIDTH_ONE_BYTE,
DMA_BURST_8_BYTES,
WIDTH * 2
};
void mDelay(uint32_t mDelay)
{
delay_us(mDelay * 1000);
}
void lcdWriteData(uint8_t data)
{
SPI_CS_LOW;
LCD_DS_HIGH;
SPI_SEND_DATA(data);
//SPI_WAIT_TX_DONE;
SPI_IS_BUSY;
SPI_CS_HIGH;
}
void lcdWriteCmd(uint8_t cmd)
{
SPI_CS_LOW;
LCD_DS_LOW;
SPI_SEND_DATA(cmd);
SPI_WAIT_TX_DONE;
SPI_CS_HIGH;
}
uint8_t lcdReadData()
{
SPI_WAIT_TX_DONE;
SPI_SEND_DATA(0xff); // Dummy data
SPI_WAIT_TX_DONE;
uint8_t data = SPI_READ_DATA;
SPI_IS_BUSY;
return data;
}
void lcdDispWindows()
{
lcdWriteCmd(0x2A);
lcdWriteData(0x00);
lcdWriteData(0x00);
lcdWriteData(0x00);
lcdWriteData(0xEF);
lcdWriteCmd(0x2B);
lcdWriteData(0x00);
lcdWriteData(0x00);
lcdWriteData(0x01);
lcdWriteData(0x3f);
lcdWriteCmd(0x2C);
}
void lcdWriteSetup(uint8_t * dataBuf, uint16_t dataCnt)
{
lcdDispWindows();
// Configure tx DMA and start it
lcdDmaTxCfg.sourceAddress = (void *)dataBuf;
//lcdDmaTxCfg.totalLength = dataCnt; // every descriptor transfer this trunk of data
SPI_CS_LOW;
LCD_DS_HIGH;
DMA_buildDescriptorChain(lcdDmaTxDesc, &lcdDmaTxCfg, dataCnt / LCD_TRANSFER_SIZE_ONCE, false);
SPI_ENABLE_TX_DMA;
}
void lcdWriteCtrl(bool startOrStop)
{
if (startOrStop)
{
DMA_loadChannelDescriptorAndRun(DMA_INSTANCE_MP, lcdDmaTxCh, lcdDmaTxDesc);
}
else
{
extern void DMA_stopChannelNoWait(DmaInstance_e instance, uint32_t channel);
DMA_stopChannelNoWait(DMA_INSTANCE_MP, lcdDmaTxCh);
SPI_CS_HIGH;
}
}
void lcdDispColor(uint16_t color)
{
//lcdFillColorBuf(color);
for (int i = 0; i < HEIGHT; i++)
{
lcdWriteCtrl(true);
}
}
void lcdReadId()
{
uint8_t id1, id2, id3;
LCD_RST_HIGH;
mDelay(150); // Delay 200ms
LCD_RST_LOW;
mDelay(300); // Delay 400ms
LCD_RST_HIGH;
mDelay(400); // Delay 500ms
lcdWriteData(0x04);
(void)lcdReadData(); // Dummy
id1 = lcdReadData();
id2 = lcdReadData();
id3 = lcdReadData();
printf("LCD ID: %02x, %02x, %02x \r\n", id1, id2, id3);
}
static void lcdGpioInit()
{
PadConfig_t config;
PAD_getDefaultConfig(&config);
// Cs pin
config.mux = SPI_CS_PAD_ALT_FUNC;
PAD_setPinConfig(SPI_CS_PAD_ADDR, &config);
GpioPinConfig_t gpioCfg;
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
GPIO_pinConfig(SPI_CS_GPIO_INSTANCE, SPI_CS_GPIO_PIN, &gpioCfg);
// Rst pin
config.mux = LCD_RST_PAD_ALT_FUNC;
PAD_setPinConfig(LCD_RST_PAD_ADDR, &config);
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
//gpioCfg.misc.initOutput = 1;
GPIO_pinConfig(LCD_RST_GPIO_INSTANCE, LCD_RST_GPIO_PIN, &gpioCfg);
// Ds pin
config.mux = LCD_DS_PAD_ALT_FUNC;
PAD_setPinConfig(LCD_DS_PAD_ADDR, &config);
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
GPIO_pinConfig(LCD_DS_GPIO_INSTANCE, LCD_DS_GPIO_PIN, &gpioCfg);
#if (ST7571_ENABLE)
#if 0 // if used in environment with os, use this api to adjust voltage
slpManAONIOVoltSet(IOVOLT_2_95V); // 54
APmuWakeupPadSettings_t cfg;
cfg.pullUpEn = 1;
slpManSetWakeupPadCfg(WAKEUP_PAD_4, false, &cfg); //gpio21 50
slpManAONIOPowerOn();//70
#else // used in environment without os
*(uint32_t*)0x4d020018 = 0x1; // Normal gpio: 2.8V
*(uint32_t*)0x4d020054 = 0x1b; // AON IO: 3.35V, 2.8V
*(uint32_t*)0x4d020150 = 0x7; // Enable AON gpio as wakeup pin
*(uint32_t*)0x4d020170 = 0x1; // Enable AON IO
#endif
// Lcd en pin
config.mux = LCD_EN_PAD_ALT_FUNC;
PAD_setPinConfig(LCD_EN_PAD_ADDR, &config);
gpioCfg.pinDirection = GPIO_DIRECTION_OUTPUT;
gpioCfg.misc.initOutput = 1;
GPIO_pinConfig(LCD_EN_GPIO_INSTANCE, LCD_EN_GPIO_PIN, &gpioCfg);
#endif
}
static void lcdSpiInit()
{
PadConfig_t config;
PAD_getDefaultConfig(&config);
config.mux = SPI_CLK_PAD_ALT_FUNC;
PAD_setPinConfig(SPI_CLK_PAD_ADDR, &config);
config.mux = SPI_MOSI_PAD_ALT_FUNC;
PAD_setPinConfig(SPI_MOSI_PAD_ADDR, &config);
config.mux = SPI_MISO_PAD_ALT_FUNC;
PAD_setPinConfig(SPI_MISO_PAD_ADDR, &config);
// Enable spi clock
GPR_clockEnable(SPI_APB_CLOCK);
GPR_clockEnable(SPI_FUNC_CLOCK);
// Disable spi first
SPI->CR1 = 0;
// Pol = 0; PHA = 0; Data width = 8
SPI->CR0 = 0x7;
// lcd spi clock choose 26M by default to speed up the fps.
CLOCK_clockEnable(CLK_HF51M); // open 51M
CLOCK_setClockSrc(FCLK_SPI0, FCLK_SPI0_SEL_51M); // choose 51M
SPI->CPSR = 2 & SPI_CPSR_CPSDVSR_Msk; // 2 division, to 26M
SPI->CR0 = (SPI->CR0 & ~SPI_CR0_SCR_Msk) | 0;
// Enable spi
SPI->CR1 = SPI_CR1_SSE_Msk;
}
void lcdWriteData16(uint16_t data)
{
lcdWriteData(data >> 8);
lcdWriteData(data);
}
void lcdDispPic(uint8_t * pic)
{
#if (ST7789V2_ENABLE)
int i, j;
lcdDispWindows();
for (i = 0; i < HEIGHT; i++)
{
for (j = 0; j < WIDTH; j++)
{
lcdWriteData16(pic[j*2 + HEIGHT*i*2]);
}
}
#elif (ST7571_ENABLE)
displayPic_60x80(pic);
#endif
}
void lcdClearScreen()
{
#if (ST7571_ENABLE)
st7571CleanScreen();
#endif
}
void lcdInit(pTxCb txCb)
{
lcdSpiInit();
lcdGpioInit();
lcdReadId();
#if (ST7789V2_ENABLE)
st7789v2_init();
#endif
#if (ST7571_ENABLE)
st7571_init();
lcdClearScreen();
#else
// Tx config
DMA_init(DMA_INSTANCE_MP);
lcdDmaTxCh = DMA_openChannel(DMA_INSTANCE_MP);
DMA_setChannelRequestSource(DMA_INSTANCE_MP, lcdDmaTxCh, (DmaRequestSource_e)SPI_DMA_TX_REQID);
DMA_rigisterChannelCallback(DMA_INSTANCE_MP, lcdDmaTxCh, txCb);
//DMA_transferSetup(DMA_INSTANCE_MP, lcdDmaTxCh, &lcdDmaTxCfg);
//DMA_transferSetup(DMA_INSTANCE_MP, lcdDmaTxCh, &lcdDmaConfig);
#endif
}

View File

@@ -0,0 +1,218 @@
#include "lcdDrv.h"
uint8_t clearScreen[128] = {0};
#define USE_DMA
#ifdef USE_DMA
static DmaTransferConfig_t st7571DmaTxCfg =
{
NULL,
(void *)&(SPI->DR),
DMA_FLOW_CONTROL_TARGET,
DMA_ADDRESS_INCREMENT_SOURCE,
DMA_DATA_WIDTH_ONE_BYTE,
DMA_BURST_8_BYTES,
0
};
static DmaDescriptor_t __ALIGNED(16) st7571DmaTxDesc[1];
int8_t st7571DmaTxCh;
bool isDMADone = false;
uint8_t st7571DmaSrc[128] = {0};
uint8_t *pLcdData = NULL;
static void st7571DmaEventCb(uint32_t event)
{
switch(event)
{
case DMA_EVENT_END:
isDMADone = true;
SPI_CS_HIGH;
//DMA_stopChannel(DMA_INSTANCE_MP, st7571DmaTxCh, false);
break;
case DMA_EVENT_ERROR:
default:
break;
}
}
void st7571DmaInit()
{
// Tx config
DMA_init(DMA_INSTANCE_MP);
st7571DmaTxCh = DMA_openChannel(DMA_INSTANCE_MP);
DMA_setChannelRequestSource(DMA_INSTANCE_MP, st7571DmaTxCh, (DmaRequestSource_e)SPI_DMA_TX_REQID);
DMA_rigisterChannelCallback(DMA_INSTANCE_MP, st7571DmaTxCh, st7571DmaEventCb);
SPI_ENABLE_TX_DMA;
}
void st7571WriteCtrl(uint32_t totalLen)
{
// Configure tx DMA and start it
st7571DmaTxCfg.sourceAddress = (void *)pLcdData;
st7571DmaTxCfg.totalLength = totalLen; // every descriptor transfer this trunk of data
SPI_CS_LOW;
LCD_DS_HIGH;
DMA_buildDescriptorChain(st7571DmaTxDesc, &st7571DmaTxCfg, 1, true);
//SPI_ENABLE_TX_DMA;
DMA_loadChannelDescriptorAndRun(DMA_INSTANCE_MP, st7571DmaTxCh, st7571DmaTxDesc);
}
#endif
void st7571_init()
{
//--------------------------------ST7571 reset sequence------------------------------------//
LCD_RST_HIGH;
mDelay(50); //Delay 100ms
LCD_RST_LOW;
mDelay(150); //Delay 200ms
LCD_RST_HIGH;
mDelay(250); //Delay 500ms
lcdWriteCmd(0xAE);
lcdWriteCmd(0xE2);
lcdWriteCmd(0x38);
lcdWriteCmd(0xE1);
lcdWriteCmd(0xAB);
lcdWriteCmd(0x54);
lcdWriteCmd(0x48);
lcdWriteCmd(0x80);
lcdWriteCmd(0xB8);
lcdWriteCmd(0xA2);
lcdWriteCmd(0xA0);
lcdWriteCmd(0xc8);
lcdWriteCmd(0x25);
lcdWriteCmd(0x81);
//lcdWriteCmd(v0); ////////////////////////////////////////////
lcdWriteCmd(0x23);
lcdWriteCmd(0x40);//START LINE
lcdWriteCmd(0x00);
lcdWriteCmd(0x44);//START LINE
lcdWriteCmd(0x00);
lcdWriteCmd(0x2c); mDelay(10);
lcdWriteCmd(0x2e); mDelay(10);
lcdWriteCmd(0x2F); mDelay(10);
lcdWriteCmd(0xAF);//DISPLAY ON
lcdWriteCmd(0x7B);
lcdWriteCmd(0x11); // 0x11=black/white mode; 0x10=gray mode;
lcdWriteCmd(0x00);
mDelay(10);
//disp_off();
mDelay(50);
#ifdef USE_DMA
st7571DmaInit();
#endif
}
void lcdAddress(uint8_t page, uint8_t column)
{
lcdWriteCmd(0xB0 + page);
lcdWriteCmd(((column >> 4) & 0x0f) + 0x10); // column addr MSB
lcdWriteCmd(column & 0x0f); // column addr LSB
}
void st7571CleanScreen(void)
{
uint8_t j;
#ifdef USE_DMA
pLcdData = clearScreen;
#else
uint8_t i;
#endif
for(j = 0; j < 16; j++)
{
lcdAddress(j, 0);
#ifndef USE_DMA
for(i = 0; i < 128; i++)
{
lcdWriteData(0x00);
}
#else
st7571WriteCtrl(128);
do
{
delay_us(1);
}while (isDMADone == false);
isDMADone = false;
#endif
}
}
void displayPic_60x80(uint8_t *p)
{
#ifndef USE_DMA
uint32_t k;
#endif
uint32_t n;
st7571CleanScreen();
for(n = 0; n < 10; n++) // 16 page
{
lcdAddress(n, 0);
#ifndef USE_DMA
for(k = 0; k < 60; k++)// every page 64byte, total 1k
{
lcdWriteData(p[k + 60 * n]);
}
#else
pLcdData = p + 60 * n;
st7571WriteCtrl(60);
do
{
delay_us(1);
}while (isDMADone == false);
isDMADone = false;
#endif
}
}
void testResolution()
{
st7571CleanScreen();
uint32_t k, n;
for (n = 0; n < 16; n++)
{
lcdAddress(n, 0); // set page and initial column
for(k = 0; k < 64/4; k++)// every page 64byte, total 1k
{
lcdWriteData(0xff); // write one byte 1
lcdWriteData(0xff); // write one byte 1 again
lcdWriteData(0); // write one byte 0
lcdWriteData(0); // write one byte 0 again
}
}
}

View File

@@ -0,0 +1,84 @@
#include "lcdDrv.h"
void st7789v2_init()
{
//--------------------------------ST7789V reset sequence------------------------------------//
LCD_RST_HIGH;
mDelay(50); //Delay 100ms
LCD_RST_LOW;
mDelay(150); //Delay 200ms
LCD_RST_HIGH;
mDelay(250); //Delay 500ms
//-------------------------------Color Mode---------------------------------------------//
lcdWriteCmd(0x11);
mDelay (120); //Delay 120ms
//--------------------------------Display Setting------------------------------------------//
lcdWriteCmd(0x36);
lcdWriteData(0x00);
lcdWriteCmd(0x3a);
lcdWriteData(0x05);
//--------------------------------ST7789V Frame rate setting----------------------------------//
lcdWriteCmd(0xb2);
lcdWriteData(0x0c);
lcdWriteData(0x0c);
lcdWriteData(0x00);
lcdWriteData(0x33);
lcdWriteData(0x33);
lcdWriteCmd(0xb7);
lcdWriteData(0x35);
//--------------------------------ST7789V Power setting--------------------------------------//
lcdWriteCmd(0xbb);
lcdWriteData(0x20);
lcdWriteCmd(0xc0);
lcdWriteData(0x2c);
lcdWriteCmd(0xc2);
lcdWriteData(0x01);
lcdWriteCmd(0xc3);
lcdWriteData(0x0b);
lcdWriteCmd(0xc4);
lcdWriteData(0x20);
lcdWriteCmd(0xc6);
lcdWriteData(0x0f);
lcdWriteCmd(0xd0);
lcdWriteData(0xa4);
lcdWriteData(0xa1);
//--------------------------------ST7789V gamma setting---------------------------------------//
lcdWriteCmd(0xe0);
lcdWriteData(0xd0);
lcdWriteData(0x03);
lcdWriteData(0x09);
lcdWriteData(0x0e);
lcdWriteData(0x11);
lcdWriteData(0x3d);
lcdWriteData(0x47);
lcdWriteData(0x55);
lcdWriteData(0x53);
lcdWriteData(0x1a);
lcdWriteData(0x16);
lcdWriteData(0x14);
lcdWriteData(0x1f);
lcdWriteData(0x22);
lcdWriteCmd(0xe1);
lcdWriteData(0xd0);
lcdWriteData(0x02);
lcdWriteData(0x08);
lcdWriteData(0x0d);
lcdWriteData(0x12);
lcdWriteData(0x2c);
lcdWriteData(0x43);
lcdWriteData(0x55);
lcdWriteData(0x53);
lcdWriteData(0x1e);
lcdWriteData(0x1b);
lcdWriteData(0x19);
lcdWriteData(0x20);
lcdWriteData(0x22);
lcdWriteCmd(0x29);
}

View File

@@ -0,0 +1,170 @@
/****************************************************************************
*
* Copy right: 2018 Copyrigths of AirM2M Ltd.
* File name: ntc.c
* Description:
* History:
*
****************************************************************************/
#include <stdint.h>
#include "ntc.h"
#define NCP15XH103F03RC
#if defined(NCP15XH103F03RC)
static const int32_t gNTCLut[65] = {
253347, // T:253.35 Rntc:0.0k ADC code:0 Input voltage:0uV
187444, // T:187.44 Rntc:0.159k ADC code:64 Input voltage:18750uV
149195, // T:149.2 Rntc:0.323k ADC code:128 Input voltage:37500uV
128368, // T:128.37 Rntc:0.492k ADC code:192 Input voltage:56250uV
115301, // T:115.3 Rntc:0.667k ADC code:256 Input voltage:75000uV
105493, // T:105.49 Rntc:0.847k ADC code:320 Input voltage:93750uV
97670, // T:97.67 Rntc:1.034k ADC code:384 Input voltage:112500uV
91187, // T:91.19 Rntc:1.228k ADC code:448 Input voltage:131250uV
85596, // T:85.6 Rntc:1.429k ADC code:512 Input voltage:150000uV
80693, // T:80.69 Rntc:1.636k ADC code:576 Input voltage:168750uV
76336, // T:76.34 Rntc:1.852k ADC code:640 Input voltage:187500uV
72403, // T:72.4 Rntc:2.075k ADC code:704 Input voltage:206250uV
68803, // T:68.8 Rntc:2.308k ADC code:768 Input voltage:225000uV
65478, // T:65.48 Rntc:2.549k ADC code:832 Input voltage:243750uV
62389, // T:62.39 Rntc:2.8k ADC code:896 Input voltage:262500uV
59508, // T:59.51 Rntc:3.061k ADC code:960 Input voltage:281250uV
56829, // T:56.83 Rntc:3.333k ADC code:1024 Input voltage:300000uV
54289, // T:54.29 Rntc:3.617k ADC code:1088 Input voltage:318750uV
51869, // T:51.87 Rntc:3.913k ADC code:1152 Input voltage:337500uV
49556, // T:49.56 Rntc:4.222k ADC code:1216 Input voltage:356250uV
47337, // T:47.34 Rntc:4.545k ADC code:1280 Input voltage:375000uV
45200, // T:45.2 Rntc:4.884k ADC code:1344 Input voltage:393750uV
43135, // T:43.14 Rntc:5.238k ADC code:1408 Input voltage:412500uV
41134, // T:41.13 Rntc:5.61k ADC code:1472 Input voltage:431250uV
39186, // T:39.19 Rntc:6.0k ADC code:1536 Input voltage:450000uV
37287, // T:37.29 Rntc:6.41k ADC code:1600 Input voltage:468750uV
35433, // T:35.43 Rntc:6.842k ADC code:1664 Input voltage:487500uV
33620, // T:33.62 Rntc:7.297k ADC code:1728 Input voltage:506250uV
31842, // T:31.84 Rntc:7.778k ADC code:1792 Input voltage:525000uV
30095, // T:30.1 Rntc:8.286k ADC code:1856 Input voltage:543750uV
28377, // T:28.38 Rntc:8.824k ADC code:1920 Input voltage:562500uV
26680, // T:26.68 Rntc:9.394k ADC code:1984 Input voltage:581250uV
25000, // T:25.0 Rntc:10.0k ADC code:2048 Input voltage:600000uV
23332, // T:23.33 Rntc:10.645k ADC code:2112 Input voltage:618750uV
21675, // T:21.68 Rntc:11.333k ADC code:2176 Input voltage:637500uV
20024, // T:20.02 Rntc:12.069k ADC code:2240 Input voltage:656250uV
18382, // T:18.38 Rntc:12.857k ADC code:2304 Input voltage:675000uV
16741, // T:16.74 Rntc:13.704k ADC code:2368 Input voltage:693750uV
15100, // T:15.1 Rntc:14.615k ADC code:2432 Input voltage:712500uV
13455, // T:13.46 Rntc:15.6k ADC code:2496 Input voltage:731250uV
11801, // T:11.8 Rntc:16.667k ADC code:2560 Input voltage:750000uV
10137, // T:10.14 Rntc:17.826k ADC code:2624 Input voltage:768750uV
8454, // T:8.45 Rntc:19.091k ADC code:2688 Input voltage:787500uV
6750, // T:6.75 Rntc:20.476k ADC code:2752 Input voltage:806250uV
5022, // T:5.02 Rntc:22.0k ADC code:2816 Input voltage:825000uV
3265, // T:3.27 Rntc:23.684k ADC code:2880 Input voltage:843750uV
1472, // T:1.47 Rntc:25.556k ADC code:2944 Input voltage:862500uV
-361, // T:-0.36 Rntc:27.647k ADC code:3008 Input voltage:881250uV
-2238, // T:-2.24 Rntc:30.0k ADC code:3072 Input voltage:900000uV
-4171, // T:-4.17 Rntc:32.667k ADC code:3136 Input voltage:918750uV
-6170, // T:-6.17 Rntc:35.714k ADC code:3200 Input voltage:937500uV
-8248, // T:-8.25 Rntc:39.231k ADC code:3264 Input voltage:956250uV
-10419, // T:-10.42 Rntc:43.333k ADC code:3328 Input voltage:975000uV
-12711, // T:-12.71 Rntc:48.182k ADC code:3392 Input voltage:993750uV
-15137, // T:-15.14 Rntc:54.0k ADC code:3456 Input voltage:1012500uV
-17727, // T:-17.73 Rntc:61.111k ADC code:3520 Input voltage:1031250uV
-20519, // T:-20.52 Rntc:70.0k ADC code:3584 Input voltage:1050000uV
-23562, // T:-23.56 Rntc:81.429k ADC code:3648 Input voltage:1068750uV
-26937, // T:-26.94 Rntc:96.667k ADC code:3712 Input voltage:1087500uV
-30762, // T:-30.76 Rntc:118.0k ADC code:3776 Input voltage:1106250uV
-35224, // T:-35.22 Rntc:150.0k ADC code:3840 Input voltage:1125000uV
-40677, // T:-40.68 Rntc:203.333k ADC code:3904 Input voltage:1143750uV
-47755, // T:-47.76 Rntc:310.0k ADC code:3968 Input voltage:1162500uV
-57225, // T:-57.23 Rntc:630.0k ADC code:4032 Input voltage:1181250uV
-69859, // T:-69.86 Rntc:10000.0k ADC code:4096 Input voltage:1200000uV
};
#elif defined(NCP15WF104F03RC)
static const int32_t gNTCLut[65] = {
175093, // T:175.09 Rntc:0.0k ADC code:0 Input voltage:0uV
140197, // T:140.2 Rntc:1.587k ADC code:64 Input voltage:18750uV
116573, // T:116.57 Rntc:3.226k ADC code:128 Input voltage:37500uV
102838, // T:102.84 Rntc:4.918k ADC code:192 Input voltage:56250uV
93457, // T:93.46 Rntc:6.667k ADC code:256 Input voltage:75000uV
86333, // T:86.33 Rntc:8.475k ADC code:320 Input voltage:93750uV
80598, // T:80.6 Rntc:10.345k ADC code:384 Input voltage:112500uV
75787, // T:75.79 Rntc:12.281k ADC code:448 Input voltage:131250uV
71646, // T:71.65 Rntc:14.286k ADC code:512 Input voltage:150000uV
67994, // T:67.99 Rntc:16.364k ADC code:576 Input voltage:168750uV
64720, // T:64.72 Rntc:18.519k ADC code:640 Input voltage:187500uV
61757, // T:61.76 Rntc:20.755k ADC code:704 Input voltage:206250uV
59039, // T:59.04 Rntc:23.077k ADC code:768 Input voltage:225000uV
56524, // T:56.52 Rntc:25.49k ADC code:832 Input voltage:243750uV
54178, // T:54.18 Rntc:28.0k ADC code:896 Input voltage:262500uV
51977, // T:51.98 Rntc:30.612k ADC code:960 Input voltage:281250uV
49898, // T:49.9 Rntc:33.333k ADC code:1024 Input voltage:300000uV
47928, // T:47.93 Rntc:36.17k ADC code:1088 Input voltage:318750uV
46050, // T:46.05 Rntc:39.13k ADC code:1152 Input voltage:337500uV
44250, // T:44.25 Rntc:42.222k ADC code:1216 Input voltage:356250uV
42521, // T:42.52 Rntc:45.455k ADC code:1280 Input voltage:375000uV
40853, // T:40.85 Rntc:48.837k ADC code:1344 Input voltage:393750uV
39240, // T:39.24 Rntc:52.381k ADC code:1408 Input voltage:412500uV
37676, // T:37.68 Rntc:56.098k ADC code:1472 Input voltage:431250uV
36155, // T:36.16 Rntc:60.0k ADC code:1536 Input voltage:450000uV
34671, // T:34.67 Rntc:64.103k ADC code:1600 Input voltage:468750uV
33220, // T:33.22 Rntc:68.421k ADC code:1664 Input voltage:487500uV
31797, // T:31.8 Rntc:72.973k ADC code:1728 Input voltage:506250uV
30400, // T:30.4 Rntc:77.778k ADC code:1792 Input voltage:525000uV
29025, // T:29.03 Rntc:82.857k ADC code:1856 Input voltage:543750uV
27669, // T:27.67 Rntc:88.235k ADC code:1920 Input voltage:562500uV
26328, // T:26.33 Rntc:93.939k ADC code:1984 Input voltage:581250uV
24999, // T:25.0 Rntc:100.0k ADC code:2048 Input voltage:600000uV
23681, // T:23.68 Rntc:106.452k ADC code:2112 Input voltage:618750uV
22370, // T:22.37 Rntc:113.333k ADC code:2176 Input voltage:637500uV
21064, // T:21.06 Rntc:120.69k ADC code:2240 Input voltage:656250uV
19760, // T:19.76 Rntc:128.571k ADC code:2304 Input voltage:675000uV
18455, // T:18.46 Rntc:137.037k ADC code:2368 Input voltage:693750uV
17148, // T:17.15 Rntc:146.154k ADC code:2432 Input voltage:712500uV
15835, // T:15.84 Rntc:156.0k ADC code:2496 Input voltage:731250uV
14513, // T:14.51 Rntc:166.667k ADC code:2560 Input voltage:750000uV
13179, // T:13.18 Rntc:178.261k ADC code:2624 Input voltage:768750uV
11830, // T:11.83 Rntc:190.909k ADC code:2688 Input voltage:787500uV
10463, // T:10.46 Rntc:204.762k ADC code:2752 Input voltage:806250uV
9074, // T:9.07 Rntc:220.0k ADC code:2816 Input voltage:825000uV
7658, // T:7.66 Rntc:236.842k ADC code:2880 Input voltage:843750uV
6211, // T:6.21 Rntc:255.556k ADC code:2944 Input voltage:862500uV
4728, // T:4.73 Rntc:276.471k ADC code:3008 Input voltage:881250uV
3202, // T:3.2 Rntc:300.0k ADC code:3072 Input voltage:900000uV
1626, // T:1.63 Rntc:326.667k ADC code:3136 Input voltage:918750uV
-6, // T:-0.01 Rntc:357.143k ADC code:3200 Input voltage:937500uV
-1710, // T:-1.71 Rntc:392.308k ADC code:3264 Input voltage:956250uV
-3495, // T:-3.5 Rntc:433.333k ADC code:3328 Input voltage:975000uV
-5376, // T:-5.38 Rntc:481.818k ADC code:3392 Input voltage:993750uV
-7371, // T:-7.37 Rntc:540.0k ADC code:3456 Input voltage:1012500uV
-9506, // T:-9.51 Rntc:611.111k ADC code:3520 Input voltage:1031250uV
-11819, // T:-11.82 Rntc:700.0k ADC code:3584 Input voltage:1050000uV
-14354, // T:-14.35 Rntc:814.286k ADC code:3648 Input voltage:1068750uV
-17179, // T:-17.18 Rntc:966.667k ADC code:3712 Input voltage:1087500uV
-20397, // T:-20.4 Rntc:1180.0k ADC code:3776 Input voltage:1106250uV
-24176, // T:-24.18 Rntc:1500.0k ADC code:3840 Input voltage:1125000uV
-28836, // T:-28.84 Rntc:2033.333k ADC code:3904 Input voltage:1143750uV
-35053, // T:-35.05 Rntc:3100.0k ADC code:3968 Input voltage:1162500uV
-44840, // T:-44.84 Rntc:6300.0k ADC code:4032 Input voltage:1181250uV
-63302, // T:-63.3 Rntc:100000.0k ADC code:4096 Input voltage:1200000uV
};
#else
#error "NTC type is not defined"
#endif
int32_t ntcGetTemperature(int32_t adcInputVoltage)
{
if(adcInputVoltage <= 1200000)
{
int32_t step = 1200000 >> 6;
int32_t i = adcInputVoltage / step;
return gNTCLut[i] + ((int32_t)((gNTCLut[i + 1] - gNTCLut[i]) * (adcInputVoltage - (i * step))) / step);
}
else
{
return -256000;
}
}

View File

@@ -0,0 +1,851 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: plat_config.c
* Description: platform configuration source file
* History:
*
****************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "plat_config.h"
#include "exception_process.h"
#ifdef FEATURE_BOOTLOADER_PROJECT_ENABLE
#include "debug_trace.h"
#include "common.h"
#else
#include DEBUG_LOG_HEADER_FILE
#include "osasys.h"
#define PLAT_CONFIG_FS_ENABLE
#endif
/** \brief config file version
* \note when the order of struct \ref plat_config_fs_t and \ref plat_config_raw_flash_t field has changed,
* for example, from 1,2,3 to 1,3,2, update version to refresh flash,
* in other cases(add more fields or remove some fields from struct \ref plat_config_fs_t), it's not a must to update
*/
// external API declarations
extern uint8_t BSP_QSPI_Erase_Safe(uint32_t SectorAddress, uint32_t Size);
extern uint8_t BSP_QSPI_Write_Safe(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
extern uint8_t BSP_QSPI_Erase_Sector(uint32_t BlockAddress);
extern uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
extern uint8_t getOSState(void);
/**
\fn uint8_t BSP_CalcCrcValue(const uint8_t *buf, uint16_t bufSize)
\brief Calculate the "CRC" value of data buffer
\param[in] buf buffer pointer
\param[in] bufSize buffer size
\returns crcValue
*/
static uint8_t BSP_CalcCrcValue(const uint8_t *buf, uint16_t bufSize)
{
uint32_t i = bufSize;
uint32_t a = 1, b = 0;
EC_ASSERT(buf != NULL && bufSize > 0, buf, bufSize, 0);
for (i = bufSize; i > 0; )
{
a += (uint32_t)(buf[--i]);
b += a;
}
return (uint8_t)(((a>>24)&0xFF)^((a>>16)&0xFF)^((a>>8)&0xFF)^((a)&0xFF)^
((b>>24)&0xFF)^((b>>16)&0xFF)^((b>>8)&0xFF)^((b)&0xFF)^
(bufSize&0xFF));
}
#ifdef PLAT_CONFIG_FS_ENABLE
static uint8_t g_fsPlatConfigInitFlag = 0;
static plat_config_fs_t g_fsPlatConfig;
/**
\fn void BSP_SetDefaultFsPlatConfig(void)
\brief set default value of "g_fsPlatConfig"
\return void
*/
static void BSP_SetDefaultFsPlatConfig(void)
{
g_fsPlatConfigInitFlag = 1;
memset(&g_fsPlatConfig, 0x0, sizeof(g_fsPlatConfig));
g_fsPlatConfig.atPortBaudRate = 115200;
}
void BSP_LoadPlatConfigFromFs(void)
{
OSAFILE fp = PNULL;
UINT32 readCount = 0;
UINT8 crcCheck = 0;
config_file_header_t fileHeader;
/*
* open NVM file
*/
fp = OsaFopen("plat_config", "rb"); //read only
if (fp == PNULL)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LoadPlatConfig_1, P_ERROR,
"Can't open 'plat_config' file, use the defult value");
BSP_SetDefaultFsPlatConfig();
BSP_SavePlatConfigToFs();
return;
}
/*
* read file header
*/
readCount = OsaFread(&fileHeader, sizeof(config_file_header_t), 1, fp);
if (readCount != 1)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LoadPlatConfig_2, P_ERROR,
"Can't read 'plat_config' file header, use the defult value");
OsaFclose(fp);
BSP_SetDefaultFsPlatConfig();
BSP_SavePlatConfigToFs();
return;
}
/*
* read file body, check validation and handle compatiblity issue
*/
if(fileHeader.version != FS_PLAT_CONFIG_FILE_CURRENT_VERSION)
{
if(fileHeader.version == 0)
{
}
// handle future version below
else if(0)
{
}
else
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LoadPlatConfig_5, P_ERROR,
"'plat_config' version:%d not right, use the defult value", fileHeader.version);
OsaFclose(fp);
BSP_SetDefaultFsPlatConfig();
BSP_SavePlatConfigToFs();
}
}
else
{
if(fileHeader.fileBodySize != sizeof(g_fsPlatConfig))
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LoadPlatConfig_3, P_ERROR,
"'plat_config' version:%d file body size not right: (%u/%u), use the defult value",
fileHeader.version, fileHeader.fileBodySize, sizeof(plat_config_fs_t));
OsaFclose(fp);
BSP_SetDefaultFsPlatConfig();
BSP_SavePlatConfigToFs();
}
else
{
readCount = OsaFread(&g_fsPlatConfig, sizeof(g_fsPlatConfig), 1, fp);
crcCheck = BSP_CalcCrcValue((uint8_t *)&g_fsPlatConfig, sizeof(g_fsPlatConfig));
OsaFclose(fp);
if (readCount != 1 || crcCheck != fileHeader.checkSum)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LoadPlatConfig_4, P_ERROR,
"Can't read 'plat_config' version:%d file body, or body not right, (%u/%u), use the defult value",
fileHeader.version, crcCheck, fileHeader.checkSum);
BSP_SetDefaultFsPlatConfig();
BSP_SavePlatConfigToFs();
}
else
{
g_fsPlatConfigInitFlag = 1;
}
}
}
return;
}
void BSP_SetFsPorDefaultValue(void)
{
bool fsCfgChanged = false;
if(g_fsPlatConfig.ecSclkCfg != 0)
{
g_fsPlatConfig.ecSclkCfg = 0;
fsCfgChanged = true;
}
if(fsCfgChanged)
{
BSP_SavePlatConfigToFs();
}
}
void BSP_SavePlatConfigToFs(void)
{
OSAFILE fp = PNULL;
UINT32 writeCount = 0;
config_file_header_t fileHeader;
/*
* open the config file
*/
fp = OsaFopen("plat_config", "wb"); //write & create
if (fp == PNULL)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfig_1, P_ERROR,
"Can't open/create 'plat_config' file, save plat_config failed");
return;
}
/*
* write the header
*/
fileHeader.fileBodySize = sizeof(g_fsPlatConfig);
fileHeader.version = FS_PLAT_CONFIG_FILE_CURRENT_VERSION;
fileHeader.checkSum = BSP_CalcCrcValue((uint8_t *)&g_fsPlatConfig, sizeof(g_fsPlatConfig));
writeCount = OsaFwrite(&fileHeader, sizeof(config_file_header_t), 1, fp);
if (writeCount != 1)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfig_2, P_ERROR,
"Write 'plat_config' file header failed");
OsaFclose(fp);
return;
}
/*
* write the file body
*/
writeCount = OsaFwrite(&g_fsPlatConfig, sizeof(g_fsPlatConfig), 1, fp);
if (writeCount != 1)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfig_3, P_ERROR,
"Write 'plat_config' file body failed");
}
OsaFclose(fp);
return;
}
plat_config_fs_t* BSP_GetFsPlatConfig(void)
{
return &g_fsPlatConfig;
}
uint32_t BSP_GetFSAssertCount(void)
{
plat_info_layout_t platInfo;
// read
memcpy((uint8_t*)&platInfo, (void*)FLASH_MEM_PLAT_INFO_ADDR, sizeof(plat_info_layout_t));
return platInfo.fsAssertCount;
}
void BSP_SetFSAssertCount(uint32_t value)
{
plat_info_layout_t platInfo;
// read
memcpy((uint8_t*)&platInfo, (void*)FLASH_MEM_PLAT_INFO_ADDR, sizeof(plat_info_layout_t));
// modify
platInfo.fsAssertCount = value;
// erase
if(BSP_QSPI_Erase_Safe(FLASH_MEM_PLAT_INFO_NONXIP_ADDR, FLASH_MEM_PLAT_INFO_SIZE) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SetFSAssertCount_0, P_ERROR, "Erase flash error!!!");
return;
}
// write back
if(BSP_QSPI_Write_Safe((uint8_t*)&platInfo, FLASH_MEM_PLAT_INFO_NONXIP_ADDR, sizeof(plat_info_layout_t)) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SetFSAssertCount_1, P_ERROR, "Update fsAssertCount value error!!!");
}
}
#endif
plat_config_raw_flash_t g_rawFlashPlatConfig;
/**
\fn void BSP_SetDefaultRawFlashPlatConfig(void)
\brief set default value of "g_rawFlashPlatConfig"
\return void
*/
static void BSP_SetDefaultRawFlashPlatConfig(void)
{
#ifdef __USER_CODE__
g_rawFlashPlatConfig.faultAction = EXCEP_OPTION_DUMP_FLASH_RESET;//silent anable
g_rawFlashPlatConfig.startWDT = 1;//start wdt
g_rawFlashPlatConfig.uartDumpPort = 0xff; // default at port
#else
#ifdef SDK_REL_BUILD
g_rawFlashPlatConfig.faultAction = 4;//silent anable
g_rawFlashPlatConfig.startWDT = 1;//start wdt
#else
g_rawFlashPlatConfig.faultAction = 0;
g_rawFlashPlatConfig.startWDT = 0;
#endif
g_rawFlashPlatConfig.uartDumpPort = 1; // default at port
#endif
g_rawFlashPlatConfig.logControl = 0x2;
g_rawFlashPlatConfig.uartBaudRate = 3000000;
g_rawFlashPlatConfig.logLevel = P_DEBUG;
g_rawFlashPlatConfig.logPortSel = PLAT_CFG_ULG_PORT_MIX;//default MIX mode
g_rawFlashPlatConfig.usbCtrl = 0;//all en
g_rawFlashPlatConfig.usbSlpMask = 0; // no mask
g_rawFlashPlatConfig.usbSlpThd = 0;
g_rawFlashPlatConfig.pwrKeyMode = 0;
g_rawFlashPlatConfig.usbVBUSModeEn = 0;
g_rawFlashPlatConfig.usbVBUSWkupPad = 1;
g_rawFlashPlatConfig.usbNet = 0;
g_rawFlashPlatConfig.usbVcomEnBitMap = 0;
#ifdef PLAT_CONFIG_FS_ENABLE
g_rawFlashPlatConfig.atPortBaudRate = g_fsPlatConfigInitFlag ? g_fsPlatConfig.atPortBaudRate : 115200;
#else
g_rawFlashPlatConfig.atPortBaudRate = 115200;
#endif
g_rawFlashPlatConfig.fotaUrcPortSel = (PLAT_CFG_FOTA_URC_PORT_USB << 4) | 0;
g_rawFlashPlatConfig.pmuInCdrx = 1;
g_rawFlashPlatConfig.slpLimitEn = 0;
g_rawFlashPlatConfig.slpLimitTime = 0;
memset(g_rawFlashPlatConfig.resv, 0x0,PLAT_CFG_RAW_FLASH_RSVD_SIZE);
}
void BSP_SavePlatConfigToRawFlash(void)
{
plat_info_layout_t platInfo;
// read
memcpy((uint8_t*)&platInfo, (void*)FLASH_MEM_PLAT_INFO_ADDR, sizeof(plat_info_layout_t));
// modify start //
// header part
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
// body part
platInfo.config = g_rawFlashPlatConfig;
// modify end //
// write back
#ifndef FEATURE_BOOTLOADER_PROJECT_ENABLE
if(1 == getOSState())
{
if(BSP_QSPI_Erase_Safe(FLASH_MEM_PLAT_INFO_NONXIP_ADDR, FLASH_MEM_PLAT_INFO_SIZE) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfigToRawFlash_1, P_ERROR, "Erase flash error!!!");
return;
}
if(BSP_QSPI_Write_Safe((uint8_t*)&platInfo, FLASH_MEM_PLAT_INFO_NONXIP_ADDR, sizeof(plat_info_layout_t)) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfigToRawFlash_2, P_ERROR, "Save plat config to raw flash error!!!");
}
}
else
#endif
{
if(BSP_QSPI_Erase_Sector(FLASH_MEM_PLAT_INFO_NONXIP_ADDR) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfigToRawFlash_3, P_ERROR, "Erase flash error!!!");
return;
}
if(BSP_QSPI_Write((uint8_t*)&platInfo, FLASH_MEM_PLAT_INFO_NONXIP_ADDR, sizeof(plat_info_layout_t)) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SavePlatConfigToRawFlash_4, P_ERROR, "Save plat config to raw flash error!!!");
}
}
}
static void BSP_WriteToRawFlash(uint8_t* pBuffer, uint32_t bufferSize)
{
if(pBuffer == NULL || bufferSize == 0)
{
return;
}
#ifndef FEATURE_BOOTLOADER_PROJECT_ENABLE
if(1 == getOSState())
{
if(BSP_QSPI_Erase_Safe(FLASH_MEM_PLAT_INFO_NONXIP_ADDR, FLASH_MEM_PLAT_INFO_SIZE) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_WriteToRawFlash_1, P_ERROR, "Erase flash error!!!");
return;
}
if(BSP_QSPI_Write_Safe(pBuffer, FLASH_MEM_PLAT_INFO_NONXIP_ADDR, bufferSize) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_WriteToRawFlash_2, P_ERROR, "Save plat config to raw flash error!!!");
}
}
else
#endif
{
if(BSP_QSPI_Erase_Sector(FLASH_MEM_PLAT_INFO_NONXIP_ADDR) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_WriteToRawFlash_3, P_ERROR, "Erase flash error!!!");
return;
}
if(BSP_QSPI_Write(pBuffer, FLASH_MEM_PLAT_INFO_NONXIP_ADDR, bufferSize) != 0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_WriteToRawFlash_4, P_ERROR, "Save plat config to raw flash error!!!");
}
}
}
void BSP_LoadPlatConfigFromRawFlash(void)
{
plat_info_layout_t platInfo;
config_file_header_t header;
uint32_t fsAssertCount;
/*
* read file header
*/
memcpy((uint8_t*)&header, (void*)FLASH_MEM_PLAT_INFO_ADDR, sizeof(header));
if(header.version != RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION)
{
if(header.version == 0)
{
plat_config_raw_flash_v0_t v0Config;
BSP_SetDefaultRawFlashPlatConfig();
// migrate from old version
if(header.fileBodySize == sizeof(plat_config_raw_flash_v0_t))
{
memcpy((uint8_t*)&v0Config, (void*)(FLASH_MEM_PLAT_INFO_ADDR + sizeof(config_file_header_t)), sizeof(v0Config));
memcpy((uint8_t*)&fsAssertCount, (void*)(FLASH_MEM_PLAT_INFO_ADDR + sizeof(config_file_header_t) + sizeof(v0Config)), sizeof(fsAssertCount));
g_rawFlashPlatConfig.faultAction = v0Config.faultAction;
g_rawFlashPlatConfig.uartDumpPort = v0Config.uartDumpPort;
g_rawFlashPlatConfig.startWDT = v0Config.startWDT;
g_rawFlashPlatConfig.logControl = v0Config.logControl;
g_rawFlashPlatConfig.uartBaudRate = v0Config.uartBaudRate;
g_rawFlashPlatConfig.logLevel = v0Config.logLevel;
g_rawFlashPlatConfig.logPortSel = v0Config.logPortSel;
g_rawFlashPlatConfig.usbCtrl = v0Config.usbCtrl;
g_rawFlashPlatConfig.usbSwTrace = v0Config.usbSwTrace;
g_rawFlashPlatConfig.usbSlpMask = v0Config.usbSlpMask;
g_rawFlashPlatConfig.usbSlpThd = v0Config.usbSlpThd;
g_rawFlashPlatConfig.pwrKeyMode = v0Config.pwrKeyMode;
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
platInfo.config = g_rawFlashPlatConfig;
platInfo.fsAssertCount = fsAssertCount;
}
// version matches but size is wrong, use default value
else
{
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
platInfo.config = g_rawFlashPlatConfig;
platInfo.fsAssertCount = 0;
}
BSP_WriteToRawFlash((uint8_t*)&platInfo, sizeof(platInfo));
}
else if(0)
{
// handle future version
}
else
{
// version is invalid
BSP_SetDefaultRawFlashPlatConfig();
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
platInfo.config = g_rawFlashPlatConfig;
platInfo.fsAssertCount = 0;
BSP_WriteToRawFlash((uint8_t*)&platInfo, sizeof(platInfo));
}
}
else
{
// file body check
memcpy((uint8_t*)&g_rawFlashPlatConfig, (void*)(FLASH_MEM_PLAT_INFO_ADDR + sizeof(config_file_header_t)), sizeof(g_rawFlashPlatConfig));
if((header.fileBodySize != sizeof(plat_config_raw_flash_t)) ||
(header.checkSum != BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig))))
{
BSP_SetDefaultRawFlashPlatConfig();
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
platInfo.config = g_rawFlashPlatConfig;
platInfo.fsAssertCount = 0;
BSP_WriteToRawFlash((uint8_t*)&platInfo, sizeof(platInfo));
}
else
{
#ifdef PLAT_CONFIG_FS_ENABLE
if(g_fsPlatConfigInitFlag && g_fsPlatConfig.atPortBaudRate != g_rawFlashPlatConfig.atPortBaudRate)
{
g_rawFlashPlatConfig.atPortBaudRate = g_fsPlatConfig.atPortBaudRate;
memcpy((uint8_t*)&fsAssertCount, (void*)(FLASH_MEM_PLAT_INFO_ADDR + sizeof(config_file_header_t) + sizeof(g_rawFlashPlatConfig)), sizeof(fsAssertCount));
platInfo.header.fileBodySize = sizeof(plat_config_raw_flash_t);
platInfo.header.version = RAW_FLASH_PLAT_CONFIG_FILE_CURRENT_VERSION;
platInfo.header.checkSum = BSP_CalcCrcValue((uint8_t *)&g_rawFlashPlatConfig, sizeof(g_rawFlashPlatConfig));
platInfo.config = g_rawFlashPlatConfig;
platInfo.fsAssertCount = fsAssertCount;
BSP_WriteToRawFlash((uint8_t*)&platInfo, sizeof(platInfo));
}
#else
/* do nothing! */
#endif
}
}
}
plat_config_raw_flash_t* BSP_GetRawFlashPlatConfig(void)
{
return &g_rawFlashPlatConfig;
}
uint32_t BSP_GetPlatConfigItemValue(plat_config_id_t id)
{
switch(id)
{
case PLAT_CONFIG_ITEM_FAULT_ACTION:
return g_rawFlashPlatConfig.faultAction;
case PLAT_CONFIG_ITEM_UART_DUMP_PORT:
return g_rawFlashPlatConfig.uartDumpPort;
case PLAT_CONFIG_ITEM_START_WDT:
return g_rawFlashPlatConfig.startWDT;
case PLAT_CONFIG_ITEM_LOG_CONTROL:
return g_rawFlashPlatConfig.logControl;
case PLAT_CONFIG_ITEM_LOG_BAUDRATE:
return g_rawFlashPlatConfig.uartBaudRate;
case PLAT_CONFIG_ITEM_LOG_LEVEL:
return g_rawFlashPlatConfig.logLevel;
case PLAT_CONFIG_ITEM_ENABLE_PM:
#ifdef PLAT_CONFIG_FS_ENABLE
return g_fsPlatConfig.enablePM;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_0, P_ERROR, "Get enablePM unsupported yet!");
return 0;
#endif
case PLAT_CONFIG_ITEM_SLEEP_MODE:
#ifdef PLAT_CONFIG_FS_ENABLE
return g_fsPlatConfig.sleepMode;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_1, P_ERROR, "Get sleepMode unsupported yet!");
return 0;
#endif
case PLAT_CONFIG_ITEM_WAIT_SLEEP:
#ifdef PLAT_CONFIG_FS_ENABLE
return g_fsPlatConfig.slpWaitTime;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_2, P_ERROR, "Get slpWaitTime unsupported yet!");
return 0;
#endif
case PLAT_CONFIG_ITEM_AT_PORT_BAUDRATE:
#ifdef PLAT_CONFIG_FS_ENABLE
#if 0
EC_ASSERT(g_fsPlatConfig.atPortBaudRate == g_rawFlashPlatConfig.atPortBaudRate,
g_fsPlatConfig.atPortBaudRate, g_rawFlashPlatConfig.atPortBaudRate, 0);
#else
if(g_fsPlatConfig.atPortBaudRate != g_rawFlashPlatConfig.atPortBaudRate)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_3, P_WARNING, "non-identical baud between fs(%d) & raw(%d)!",
g_fsPlatConfig.atPortBaudRate, g_rawFlashPlatConfig.atPortBaudRate);
}
#endif
return g_fsPlatConfig.atPortBaudRate;
#else
return g_rawFlashPlatConfig.atPortBaudRate;
#endif
case PLAT_CONFIG_ITEM_AT_PORT_FRAME_FORMAT:
#ifdef PLAT_CONFIG_FS_ENABLE
return g_fsPlatConfig.atPortFrameFormat.wholeValue;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_4, P_ERROR, "Get atPortFrameFormat unsupported yet!");
return 0;
#endif
case PLAT_CONFIG_ITEM_ECSCLK_CFG:
#ifdef PLAT_CONFIG_FS_ENABLE
return g_fsPlatConfig.ecSclkCfg;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_GET_PLAT_CFG_5, P_ERROR, "Get ecSclkCfg unsupported yet!");
return 0;
#endif
case PLAT_CONFIG_ITEM_LOG_PORT_SEL:
return g_rawFlashPlatConfig.logPortSel;
case PLAT_CONFIG_ITEM_USB_CTRL:
return g_rawFlashPlatConfig.usbCtrl;
case PLAT_CONFIG_ITEM_USB_SW_TRACE_FLAG:
return g_rawFlashPlatConfig.usbSwTrace;
case PLAT_CONFIG_ITEM_USB_SLEEP_MASK:
return g_rawFlashPlatConfig.usbSlpMask;
case PLAT_CONFIG_ITEM_USB_SLEEP_THD:
return g_rawFlashPlatConfig.usbSlpThd;
case PLAT_CONFIG_ITEM_USB_VBUS_MODE_EN:
return g_rawFlashPlatConfig.usbVBUSModeEn;
case PLAT_CONFIG_ITEM_USB_VBUS_WKUP_PAD:
return g_rawFlashPlatConfig.usbVBUSWkupPad;
case PLAT_CONFIG_ITEM_PWRKEY_MODE:
return g_rawFlashPlatConfig.pwrKeyMode;
case PLAT_CONFIG_ITEM_USB_NET:
return g_rawFlashPlatConfig.usbNet;
case PLAT_CONFIG_ITEM_USB_VCOM_EN_BMP:
return g_rawFlashPlatConfig.usbVcomEnBitMap;
case PLAT_CONFIG_ITEM_FOTA_URC_PORT_SEL:
return g_rawFlashPlatConfig.fotaUrcPortSel;
case PLAT_CONFIG_ITEM_PMUINCDRX:
return g_rawFlashPlatConfig.pmuInCdrx;
case PLAT_CONFIG_ITEM_SLP_LIMIT_EN:
return g_rawFlashPlatConfig.slpLimitEn;
case PLAT_CONFIG_ITEM_SLP_LIMIT_TIME:
return g_rawFlashPlatConfig.slpLimitTime;
default:
return 0;
}
}
void BSP_SetPlatConfigItemValue(plat_config_id_t id, uint32_t value)
{
switch(id)
{
case PLAT_CONFIG_ITEM_FAULT_ACTION:
if(value <= (EXCEP_OPTION_MAX -1))
g_rawFlashPlatConfig.faultAction = value;
break;
case PLAT_CONFIG_ITEM_UART_DUMP_PORT:
g_rawFlashPlatConfig.uartDumpPort = value;
break;
case PLAT_CONFIG_ITEM_START_WDT:
if(value <= 1)
g_rawFlashPlatConfig.startWDT = value;
break;
case PLAT_CONFIG_ITEM_LOG_CONTROL:
if(value <= 2)
g_rawFlashPlatConfig.logControl = value;
break;
case PLAT_CONFIG_ITEM_LOG_BAUDRATE:
g_rawFlashPlatConfig.uartBaudRate = value;
break;
case PLAT_CONFIG_ITEM_LOG_LEVEL:
if(value <= P_ERROR)
g_rawFlashPlatConfig.logLevel = (DebugTraceLevelType_e)value;
break;
case PLAT_CONFIG_ITEM_ENABLE_PM:
#ifdef PLAT_CONFIG_FS_ENABLE
g_fsPlatConfig.enablePM = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_0, P_ERROR, "Set enablePM unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_SLEEP_MODE:
#ifdef PLAT_CONFIG_FS_ENABLE
if(value <= 4) g_fsPlatConfig.sleepMode = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_1, P_ERROR, "Set sleepMode unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_WAIT_SLEEP:
#ifdef PLAT_CONFIG_FS_ENABLE
g_fsPlatConfig.slpWaitTime = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_2, P_ERROR, "Set slpWaitTime unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_AT_PORT_BAUDRATE:
g_rawFlashPlatConfig.atPortBaudRate = value;
#ifdef PLAT_CONFIG_FS_ENABLE
g_fsPlatConfig.atPortBaudRate = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_3, P_ERROR, "Set atPortBaudRate unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_AT_PORT_FRAME_FORMAT:
#ifdef PLAT_CONFIG_FS_ENABLE
g_fsPlatConfig.atPortFrameFormat.wholeValue = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_4, P_ERROR, "Set atPortFrameFormat unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_ECSCLK_CFG:
#ifdef PLAT_CONFIG_FS_ENABLE
g_fsPlatConfig.ecSclkCfg = value;
#else
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_SET_PLAT_CFG_5, P_ERROR, "Set ecSclkCfg unsupported yet!");
#endif
break;
case PLAT_CONFIG_ITEM_LOG_PORT_SEL:
g_rawFlashPlatConfig.logPortSel = (PlatCfgUlgPort_e)value;
break;
case PLAT_CONFIG_ITEM_USB_CTRL:
g_rawFlashPlatConfig.usbCtrl = value;
break;
case PLAT_CONFIG_ITEM_USB_SW_TRACE_FLAG:
g_rawFlashPlatConfig.usbSwTrace = value;
break;
case PLAT_CONFIG_ITEM_USB_SLEEP_MASK:
g_rawFlashPlatConfig.usbSlpMask = value;
break;
case PLAT_CONFIG_ITEM_USB_SLEEP_THD:
g_rawFlashPlatConfig.usbSlpThd = value;
break;
case PLAT_CONFIG_ITEM_USB_VBUS_MODE_EN:
g_rawFlashPlatConfig.usbVBUSModeEn = value;
break;
case PLAT_CONFIG_ITEM_USB_VBUS_WKUP_PAD:
g_rawFlashPlatConfig.usbVBUSWkupPad = value;
break;
case PLAT_CONFIG_ITEM_PWRKEY_MODE:
g_rawFlashPlatConfig.pwrKeyMode = value;
break;
case PLAT_CONFIG_ITEM_USB_NET:
g_rawFlashPlatConfig.usbNet = value;
break;
case PLAT_CONFIG_ITEM_USB_VCOM_EN_BMP:
g_rawFlashPlatConfig.usbVcomEnBitMap = value;
break;
case PLAT_CONFIG_ITEM_FOTA_URC_PORT_SEL:
g_rawFlashPlatConfig.fotaUrcPortSel = value;
break;
case PLAT_CONFIG_ITEM_PMUINCDRX:
g_rawFlashPlatConfig.pmuInCdrx = value;
break;
case PLAT_CONFIG_ITEM_SLP_LIMIT_EN:
g_rawFlashPlatConfig.slpLimitEn = value;
break;
case PLAT_CONFIG_ITEM_SLP_LIMIT_TIME:
g_rawFlashPlatConfig.slpLimitTime = value;
break;
default:
break;
}
return;
}

View File

@@ -0,0 +1,182 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: adc.h
* Description: EC618 adc driver header file
* History:
****************************************************************************/
#ifndef _ADC_EC618_H
#define _ADC_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup adc_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief List of ADC clock source divider */
typedef enum
{
ADC_CLOCK_DIV_4 = 0U, /**< ADC clock is divided by 4 from input clock */
ADC_CLOCK_DIV_8 = 1U, /**< ADC clock is divided by 8 from input clock */
ADC_CLOCK_DIV_16 = 2U, /**< ADC clock is divided by 16 from input clock */
} AdcClockDivider_e;
/** \brief List of ADC channels */
typedef enum
{
ADC_CHANNEL_THERMAL = 0U, /**< ADC Thermal channel */
ADC_CHANNEL_VBAT = 1U, /**< ADC VBAT channel */
ADC_CHANNEL_AIO4 = 2U, /**< ADC AIO4 channel */
ADC_CHANNEL_AIO3 = 3U, /**< ADC AIO3 channel */
ADC_CHANNEL_AIO2 = 4U, /**< ADC AIO2 channel */
ADC_CHANNEL_AIO1 = 5U, /**< ADC AIO1 channel */
} AdcChannel_e;
/** \brief List of AIO resdiv select options */
typedef enum
{
ADC_AIO_RESDIV_RATIO_1 = 0U, /**< ADC AIO RESDIV select as VIN */
ADC_AIO_RESDIV_RATIO_14OVER16 = 1U, /**< ADC AIO RESDIV select as 14/16 VIN */
ADC_AIO_RESDIV_RATIO_12OVER16 = 2U, /**< ADC AIO RESDIV select as 12/16 VIN */
ADC_AIO_RESDIV_RATIO_10OVER16 = 3U, /**< ADC AIO RESDIV select as 10/16 VIN */
ADC_AIO_RESDIV_RATIO_8OVER16 = 4U, /**< ADC AIO RESDIV select as 8/16 VIN */
ADC_AIO_RESDIV_RATIO_7OVER16 = 5U, /**< ADC AIO RESDIV select as 7/16 VIN */
ADC_AIO_RESDIV_RATIO_6OVER16 = 6U, /**< ADC AIO RESDIV select as 6/16 VIN */
ADC_AIO_RESDIV_RATIO_5OVER16 = 7U, /**< ADC AIO RESDIV select as 5/16 VIN */
ADC_AIO_RESDIV_RATIO_4OVER16 = 8U, /**< ADC AIO RESDIV select as 4/16 VIN */
ADC_AIO_RESDIV_RATIO_3OVER16 = 9U, /**< ADC AIO RESDIV select as 3/16 VIN */
ADC_AIO_RESDIV_RATIO_2OVER16 = 10U, /**< ADC AIO RESDIV select as 2/16 VIN */
ADC_AIO_RESDIV_RATIO_1OVER16 = 11U, /**< ADC AIO RESDIV select as 1/16 VIN */
ADC_AIO_RESDIV_BYPASS = 12U, /**< BYPASS the whole ADC AIO RESDIV network(direct input) */
} AdcAioResDiv_e;
/** \brief List of VBAT resdiv select options */
typedef enum
{
ADC_VBAT_RESDIV_RATIO_8OVER16 = 0U, /**< ADC AIO RESDIV select as 8/16 VBAT */
ADC_VBAT_RESDIV_RATIO_7OVER16 = 1U, /**< ADC AIO RESDIV select as 7/16 VBAT */
ADC_VBAT_RESDIV_RATIO_6OVER16 = 2U, /**< ADC AIO RESDIV select as 6/16 VBAT */
ADC_VBAT_RESDIV_RATIO_5OVER16 = 3U, /**< ADC AIO RESDIV select as 5/16 VBAT */
ADC_VBAT_RESDIV_RATIO_4OVER16 = 4U, /**< ADC AIO RESDIV select as 4/16 VBAT */
ADC_VBAT_RESDIV_RATIO_3OVER16 = 5U, /**< ADC AIO RESDIV select as 3/16 VBAT */
ADC_VBAT_RESDIV_RATIO_2OVER16 = 6U, /**< ADC AIO RESDIV select as 2/16 VBAT */
ADC_VBAT_RESDIV_RATIO_1OVER16 = 7U, /**< ADC AIO RESDIV select as 1/16 VBAT */
} AdcVbatResdiv_e;
/** \brief ADC channel configuration */
typedef union
{
AdcAioResDiv_e aioResDiv; /**< resdiv setting, valid only for AIO channel */
AdcVbatResdiv_e vbatResDiv; /**< resdiv setting, valid only for VBAT channel */
} AdcChannelConfig_t;
/** \brief ADC configuration structure */
typedef struct
{
AdcClockDivider_e clockDivider; /**< ADC work clock source divider setting */
AdcChannelConfig_t channelConfig; /**< ADC channel configuration */
} AdcConfig_t;
/** \brief List of ADC channel users, used to compose logical channel combining with ADC physical channel
each channel can be occupied by these users at the same time, conversion request gets serviced one by one in FIFO ordering.
*/
typedef enum
{
ADC_USER_PHY = 0U, /**< Internal user ID for PHY */
ADC_USER_PLAT = 1U, /**< Internal user ID for PLAT */
ADC_USER_APP = 2U, /**< user ID for APP */
ADC_USER_MAX /**< Total number of users for one channel */
} AdcUser_t;
/**
\brief Defines callback function prototype.
Callback function will be called in ADC interrupt service routine after sample completes
\param result ADC sample result
*/
typedef void (*adcCallback_t)(uint32_t result);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name ADC Configuration */
/** \{ */
/**
\fn void ADC_getDefaultConfig(AdcConfig_t *config)
\brief Gets the ADC default configuartion.
This function sets the configuration structure to default values as below:
\code
config->clockDivider = ADC_CLOCK_DIV_4;
config->channalConfig.aioResDiv = ADC_AIO_RESDIV_BYPASS; // Note: channelConfig field is union
\endcode
\param[in] config Pointer to ADC configuration structure
*/
void ADC_getDefaultConfig(AdcConfig_t *config);
/**
\fn int32_t ADC_channelInit(AdcChannel_e channel, const AdcConfig_t *config, adcCallback_t callback)
\brief Initialize ADC specific channel
\param[in] channel ADC physical channel to be configured
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
\param[in] config Pointer to ADC configuration
\param[in] callback Function to be called when ADC conversion completes
\return 0 on success, -1 for parameter check error, -2 for AIO1 channel conflict(vref output has been enabled)
*/
int32_t ADC_channelInit(AdcChannel_e channel, AdcUser_t userID, const AdcConfig_t *config, adcCallback_t callback);
/**
\fn void ADC_channelDeInit(AdcChannel_e channel)
\brief Deinitialize ADC channel
\param[in] channel physical channel to be de-initialized, configuration of specific logical channel is invalid after this API call.
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
*/
void ADC_channelDeInit(AdcChannel_e channel, AdcUser_t userID);
/**
\fn void ADC_startConversion(uint32_t channels)
\brief Starts ADC conversion. Conversion is performed imediately when ADC is free, otherwise, the start request is put into a request queue and will be serviced later.
\param[in] channel ADC physical channel to converse
\param[in] userID user ID of specific channel, customer user is assigned with ADC_USER_APP, used to compose logical channel combining with channel parameter
\return 0 on success, -1 if request queue is full, -2 if channel has not been initialized yet
*/
int32_t ADC_startConversion(AdcChannel_e channel, AdcUser_t userID);
/**
\fn int32_t ADC_enableVrefOutput(void)
\brief Enable vref output through AIO1
\return 0 on success, -2 for AIO1 channel conflict(AIO1 input has been enabled)
\note this feature and AIO1 input is mutual exclusive
*/
int32_t ADC_enableVrefOutput(void);
/**
\fn void ADC_disableVrefOutput(void)
\brief Disable vref output through AIO1
*/
void ADC_disableVrefOutput(void);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _ADC_EC618_H */

View File

@@ -0,0 +1,117 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename: alarm.h
*
* Description: header of alarm.c, hw config for hal_alarm
*
* History: 2021.05.12 initiated by Zhao Weiqi
*
* Notes:
*
******************************************************************************/
#ifndef CHIP_ALARM_H
#define CHIP_ALARM_H
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
/**
* @brief alarmVBatHwInit
* @details configure and start vbat alarm
*
* @param voltThd100: set the threshold
* @return null
*/
void alarmVBatHwInit(uint16_t voltThd100);
/**
* @brief alarmThmHwInit
* @details configure and start themral alarm
*
* @param thmThd: set the threshold
* @param range: set the hysteresis range
* @return null
*/
void alarmThmHwInit(uint8_t thmThd, uint8_t range);
/**
* @brief alarmVBatHwDeinit
* @details stop vbat alarm
* @return null
*/
void alarmVBatHwDeinit(void);
/**
* @brief alarmThmHwDeinit
* @details stop thermal alarm
* @return null
*/
void alarmThmHwDeinit(void);
/**
* @brief alarmVBatGetIntIndicate
* @details stop thermal alarm
* @return 1: high 0: low
*/
uint8_t alarmVBatGetIntIndicate(void);
/**
* @brief alarmThmGetIntIndicate
* @details stop thermal alarm
* @return 1: high 0: low
*/
uint8_t alarmThmGetIntIndicate(void);
/**
* @brief alarmThmDisableInAdc
* @details stop thermal alarm, call in auxadc when sample the thm channel
* @return 1: disable operation down 0: do nothing
*/
bool alarmThmDisableInAdc(void);
/**
* @brief alarmThmEnableInAdc
* @details restart thermal alarm, call in auxadc when sample the thm channel
* @return 1: enable operation down 0: do nothing
*/
bool alarmThmEnableInAdc(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,34 @@
#ifndef _APMU_PERIPHERAL_
#define _APMU_PERIPHERAL_
#include <stdint.h>
#include <stdbool.h>
void apmuPeriUsbEnterStartProc(bool forceCfgPwrDown);
void apmuPeriUsbEnterAbortProc(bool forceCfgPwrDown);
void apmuPeriUsbSusp2VbusTblGuardDlyChk(uint32_t cur_tick);
void apmuPeriUsbSusp2HibGuardDlyChk(uint32_t cur_tick);
void apmuPeriUsbSleep1LateRecoverFlow(bool sleepSuccess);
void apmuPeriUsbSleep1PreRecoverFlow(bool sleepSuccess);
bool apmuPeriLpuartPreSleepProcess(void);
bool apmuPeriLpuartIsRxActive(void);
void apmuPeriStartWFITimer(uint32_t ms);
void apmuPeriDeleteWFITimer(void);
void apmuPeriDeleteCPTimer(void);
void apmuPeriClearCPTimerInterrupt(void);
void apmuPeriStartCPTimer(uint32_t cpStartTime, void* expFunc);
#endif

View File

@@ -0,0 +1,49 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: cache.h
* Description: EC618 cache controller driver header file
* History: Rev1.0 2018-07-12
*
****************************************************************************/
#ifndef _CACHE_EC618_H
#define _CACHE_EC618_H
#include "Driver_Common.h"
/**
\addtogroup icache_interface_gr
\{
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
\fn void EnableICache(void)
\brief Enables Instrution cache
\return void
*/
void EnableICache(void);
/**
\fn void DisableICache(void)
\brief Disables Instrution cache
\return void
*/
void DisableICache(void);
/**
\fn bool IsICacheEnabled(void)
\brief Check whether cache is enabled
\return enabled or not
*/
bool IsICacheEnabled(void);
/** \}*/
#ifdef __cplusplus
}
#endif
#endif /* _CACHE_EC618_H */

View File

@@ -0,0 +1,87 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename: charge.h
*
* Description: header of charge.c. api for charge status detect
*
* History: 2021.05.07 initiated by Zhao Weiqi
*
* Notes:
*
******************************************************************************/
#ifndef CHARGE_H
#define CHARGE_H
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
typedef enum
{
CHARGE_STATUS_DISCONNECT = 0,
CHARGE_STATUS_CHARGING = 1,
CHARGE_STATUS_FINISH = 2,
}chargeStatus_e;
typedef void(* chargeStatusCb)(chargeStatus_e status);
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
/**
* @brief chargeGetCurStatus
* @details Get current charge status
*
* @return charge status:
CHARGE_STATUS_DISCONNECT = 0,
CHARGE_STATUS_CHARGING = 1,
CHARGE_STATUS_FINISH = 2,
*/
chargeStatus_e chargeGetCurStatus(void);
/**
* @brief chargeHwInit
* @details init hardware
*
* @return null
*/
void chargeHwInit(void);
/**
* @brief chargeHwDeinit
* @details deinit hardware
*
* @return null
*/
void chargeHwDeinit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,509 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: clock.h
* Description: EC618 clock driver header file
* History: Rev1.0 2019-02-20
*
****************************************************************************/
#ifndef _CLOCK_EC618_H
#define _CLOCK_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup clock_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#ifndef __CLOCK_DECLARATION_DEFINED__
#define __CLOCK_DECLARATION_DEFINED__
#include "gpr_common.h"
typedef enum
{
/* clock ID with clock source select start */
CLK_CC = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 0),
CLK_APB_MP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 1),
CLK_APB_XP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 2),
CLK_SMP = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 3),
CLK_SYSTICK = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 4),
FCLK_UART0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 0, 5),
FCLK_UART1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 1, 6),
FCLK_UART2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 2, 7),
FCLK_SPI0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 3, 8),
FCLK_SPI1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 4, 9),
FCLK_I2S0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 5, 10),
FCLK_I2S1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_FCLK_EN_REG_INDEX, 6, 11),
FCLK_WDG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 0, 12),
FCLK_TIMER0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 1, 13),
FCLK_TIMER1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 2, 14),
FCLK_TIMER2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 3, 15),
FCLK_TIMER3 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 4, 16),
FCLK_TIMER4 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 5, 17),
FCLK_TIMER5 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 6, 18),
FCLK_I2C0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 7, 19),
FCLK_I2C1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 8, 20),
FCLK_USIM0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 9, 21),
FCLK_USIM1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 10, 22),
FCLK_KPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_FCLK_EN_REG_INDEX, 11, 23),
CLK_FLASH = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 9, 24),
CLK_PSRAM = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 10, 25),
CLK_CLKCAL = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 5, 26),
/* clock ID with clock source select end */
/* root clock */
CLK_MF = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 27),
CLK_32K = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 28),
CLK_HF408M = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 29),
CLK_HF204M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 0, 30),
CLK_HF102M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 1, 31),
CLK_HF51M = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 2, 32),
CLK_32K_GATED = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 3, 33),
CLK_MF_GATED = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 4, 34),
CLK_CC_MP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 5, 35),
CLK_CC_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 6, 36),
CLK_CC_CP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 7, 37),
CLK_AON = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 8, 38),
CLK_SMP_MP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 11, 39),
MFAB_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 16, 40),
AFBBR_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 17, 41),
MSMB_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 19, 42),
FLASH_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 20, 43),
PSRAM_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 21, 44),
ULOG_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 22, 45),
UTFC_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 23, 46),
ULDP_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 24, 47),
USBC_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 26, 48),
USBC_PMU_HCLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 27, 49),
USBC_REF_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 28, 50),
USBP_REF_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 29, 51),
USBC_UTMI_CLK = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_MP_CLKEN_REG_INDEX, 30, 52),
CLK_DAP_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 0, 53),
CLK_TRACE_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 1, 54),
CLK_SYSTICK_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 2, 55),
CLK_APB_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 3, 56),
CLK_SMP_AP = CONSTRUCT_CLOCK_ID(APB_GPR_TOP_AP_CLKEN_REG_INDEX, 4, 57),
PCLK_SIPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 1, 58),
PCLK_AON = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 2, 59),
PCLK_CPMU = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 3, 60),
PCLK_PMDIG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 4, 61),
PCLK_RFDIG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 5, 62),
PCLK_PAD = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 6, 63),
PCLK_GPIO = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 7, 64),
PCLK_FUSE = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 8, 65),
PCLK_TRNG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 9, 66),
PCLK_USBP = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 10, 67),
PCLK_LPUC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 11, 68),
PCLK_UART0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 12, 69),
PCLK_UART1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 13, 70),
PCLK_UART2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 14, 71),
PCLK_SPI0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 15, 72),
PCLK_SPI1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 16, 73),
PCLK_I2S0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 17, 74),
PCLK_I2S1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_MP_PCLK_EN_REG_INDEX, 18, 75),
PCLK_WDG = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 0, 76),
PCLK_TIMER0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 1, 77),
PCLK_TIMER1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 2, 78),
PCLK_TIMER2 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 3, 79),
PCLK_TIMER3 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 4, 80),
PCLK_TIMER4 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 5, 81),
PCLK_TIMER5 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 6, 82),
PCLK_IPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 7, 83),
PCLK_I2C0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 8, 84),
PCLK_I2C1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 9, 85),
PCLK_USIM0 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 10, 86),
PCLK_USIM1 = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 11, 87),
PCLK_KPC = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 12, 88),
PCLK_ONEW = CONSTRUCT_CLOCK_ID(APB_GPR_APB_AP_PCLK_EN_REG_INDEX, 13, 89),
TOP_PBRG_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 0, 90),
TOP_PBRG_PCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 1, 91),
TOP_GPR_PCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_TOP_CLKEN_REG_INDEX, 2, 92),
TRACE_CLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 1, 93),
ETM_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 2, 94),
ROMTABLE_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 3, 95),
TPIU_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 4, 96),
CACHE_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 5, 97),
FABSUB_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 6, 98),
SBU_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 7, 99),
PBRG_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 8, 100),
SPIS_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 9, 101),
XIC_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 10, 102),
ULOG_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 11, 103),
TMU_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 12, 104),
SCT_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 13, 105),
UTFC_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 16, 106),
ULDP_RMI_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 17, 107),
SCT_HCLK = CONSTRUCT_CLOCK_ID(RMI_GPR_XPSYS_CLKEN_REG_INDEX, 18, 108),
INVALID_CLK = CONSTRUCT_CLOCK_ID(CLKEN_REG_INDEX_MAX, 0, 109)
} ClockId_e;
/** \brief List of all configurable module's functional clock sources */
typedef enum
{
// top clk sel
/** Core clock sourced from 26M */
CLK_CC_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 0, CLK_MF),
/** Core clock sourced from 204M */
CLK_CC_SEL_204M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 1, CLK_HF204M),
/** Core clock sourced from 102M */
CLK_CC_SEL_102M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 2, CLK_HF102M),
/** Core clock sourced from 32K */
CLK_CC_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_CC), 3, CLK_32K),
/** APB MP clock sourced from 26M */
CLK_APB_MP_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP), 0, CLK_MF),
/** APB MP clock sourced from 51M */
CLK_APB_MP_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP), 1U, CLK_HF51M),
/** APB XP clock sourced from 26M */
CLK_APB_XP_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP), 0, CLK_MF),
/** APB XP sourced from 51M */
CLK_APB_XP_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP), 1U, CLK_HF51M),
/** Systick clock sourced from 32K */
CLK_SYSTICK_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK), 0, CLK_32K),
/** Systick clock sourced from 26M */
CLK_SYSTICK_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK), 1U, CLK_MF),
// apb mp func clk sel
/** UART0 clock sourced from 26M */
FCLK_UART0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART0), 0, CLK_MF_GATED),
/** UART0 clock sourced from 51M */
FCLK_UART0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART0), 1U, CLK_HF51M),
/** UART1 clock sourced from 26M */
FCLK_UART1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART1), 0, CLK_MF_GATED),
/** UART1 clock sourced from 51M */
FCLK_UART1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART1), 1U, CLK_HF51M),
/** UART2 clock sourced from 26M */
FCLK_UART2_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART2), 0, CLK_MF_GATED),
/** UART2 clock sourced from 51M */
FCLK_UART2_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_UART2), 1U, CLK_HF51M),
/** SPI0 clock sourced from 26M */
FCLK_SPI0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0), 0, CLK_MF_GATED),
/** SPI0 clock sourced from 51M */
FCLK_SPI0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0), 1U, CLK_HF51M),
/** SPI1 clock sourced from 26M */
FCLK_SPI1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1), 0, CLK_MF_GATED),
/** SPI1 clock sourced from 51M */
FCLK_SPI1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1), 1U, CLK_HF51M),
/** I2S0 clock sourced from 26M */
FCLK_I2S0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0), 0, CLK_MF_GATED),
/** I2S0 clock sourced from 51M */
FCLK_I2S0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0), 1U, CLK_HF51M),
/** I2S1 clock sourced from 26M */
FCLK_I2S1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1), 0, CLK_MF_GATED),
/** I2S1 clock sourced from 51M */
FCLK_I2S1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1), 1U, CLK_HF51M),
// apb ap func clk sel
/** WDG clock sourced from 32K */
FCLK_WDG_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_WDG), 0, CLK_32K_GATED),
/** WDG clock sourced from 26M */
FCLK_WDG_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_WDG), 1U, CLK_MF_GATED),
/** TIMER0 clock sourced from 32K */
FCLK_TIMER0_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0), 0, CLK_32K_GATED),
/** TIMER0 clock sourced from 26M */
FCLK_TIMER0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0), 1U, CLK_MF_GATED),
/** TIMER1 clock sourced from 32K */
FCLK_TIMER1_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1), 0, CLK_32K_GATED),
/** TIMER1 clock sourced from 26M */
FCLK_TIMER1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1), 1U, CLK_MF_GATED),
/** TIMER2 clock sourced from 32K */
FCLK_TIMER2_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2), 0, CLK_32K_GATED),
/** TIMER2 clock sourced from 26M */
FCLK_TIMER2_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2), 1U, CLK_MF_GATED),
/** TIMER3 clock sourced from 32K */
FCLK_TIMER3_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3), 0, CLK_32K_GATED),
/** TIMER3 clock sourced from 26M */
FCLK_TIMER3_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3), 1U, CLK_MF_GATED),
/** TIMER4 clock sourced from 32K */
FCLK_TIMER4_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4), 0, CLK_32K_GATED),
/** TIMER4 clock sourced from 26M */
FCLK_TIMER4_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4), 1U, CLK_MF_GATED),
/** TIMER5 clock sourced from 32K */
FCLK_TIMER5_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5), 0, CLK_32K_GATED),
/** TIMER5 clock sourced from 26M */
FCLK_TIMER5_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5), 1U, CLK_MF_GATED),
/** I2C0 clock sourced from 26M */
FCLK_I2C0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0), 0, CLK_MF_GATED),
/** I2C0 clock sourced from 51M */
FCLK_I2C0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0), 1U, CLK_HF51M),
/** I2C1 clock sourced from 26M */
FCLK_I2C1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1), 0, CLK_MF_GATED),
/** I2C1 clock sourced from 51M */
FCLK_I2C1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1), 1U, CLK_HF51M),
/** USIM0 clock sourced from 26M */
FCLK_USIM0_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0), 0, CLK_MF_GATED),
/** USIM0 clock sourced from 51M */
FCLK_USIM0_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0), 1U, CLK_HF51M),
/** USIM1 clock sourced from 26M */
FCLK_USIM1_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1), 0, CLK_MF_GATED),
/** USIM1 clock sourced from 51M */
FCLK_USIM1_SEL_51M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1), 1U, CLK_HF51M),
/** KPC clock sourced from 26M */
FCLK_KPC_SEL_32K = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_KPC), 0, CLK_32K_GATED),
/** KPC clock sourced from 51M */
FCLK_KPC_SEL_26M = MAKE_CLOCK_SEL_VALUE(GET_INDEX_FROM_CLOCK_ID(FCLK_KPC), 1U, CLK_MF_GATED),
} ClockSelect_e;
#endif //__CLOCK_DECLARATION_DEFINED__
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/** \name Clock Configuration */
/* \{ */
/**
\fn int32_t CLOCK_clockEnable(ClockId_e id)
\brief Enable clock for selected module
\param[in] id clock item to enable
\return ARM_DRIVER_OK if the setting is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id)
*/
int32_t CLOCK_clockEnable(ClockId_e id);
/**
\fn void CLOCK_clockReset(ClockId_e id)
\brief Reset clock for selected module
\param[in] id clock item to reset
*/
void CLOCK_clockReset(ClockId_e id);
/**
\fn void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount)
\brief Update clock tree node item value, interrnal used only
\param[in] id clock item to update
\param[in] parentId parent clock id
\param[in] enableCount new enable count
*/
void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount);
/**
\fn void CLOCK_clockDisable(ClockId_e id)
\brief Disable clock for selected module
\param[in] id clock item to disable
*/
void CLOCK_clockDisable(ClockId_e id);
/**
\fn int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select)
\brief Set clock source for selected module
\param[in] id clock item to set
\param[in] select select one of clock sources \ref ClockSelect_e
\return ARM_DRIVER_OK if the setting is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id)
ARM_DRIVER_ERROR if specific clock has been enabled
*/
int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select);
/**
\fn int32_t CLOCK_setClockDiv(ClockId_e id, uint32 div)
\brief Set clock divider for selected module
\param[in] id clock item to set
\param[in] div divider value
\return ARM_DRIVER_OK if the setting is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure(setting is not available for specified clock id or div value is set to 0)
ARM_DRIVER_ERROR if specific clock has been enabled
*/
int32_t CLOCK_setClockDiv(ClockId_e id, uint32_t div);
/**
\fn uint32_t CLOCK_getClockFreq(ClockId_e id)
\brief Get clock frequency for selected module
\param[in] id clock item to get
\return clock frequency in unit of HZ
*/
uint32_t CLOCK_getClockFreq(ClockId_e id);
/**
\fn int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config)
\brief fracdiv clock config
\param[in] config pointer to fracdiv setting
\return ARM_DRIVER_OK if the setting is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
*/
int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config);
/**
\fn void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id)
\brief fracdiv out clock enable
\param[in] id fracdiv out clock id
*/
void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id);
/**
\fn void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id)
\brief fracdiv out clock disable
\param[in] id fracdiv out clock id
*/
void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id);
/**
\fn void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div)
\brief set fracdiv out clock divider
\param[in] id fracdiv out clock id
\param[in] div divider ratio to set
*/
void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div);
/**
\fn void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src)
\brief select bclk source
\param[in] id bclk id
\param[in] src clock source to set
*/
void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src);
/**
\fn void CLOCK_setBclkDiv(BclkId_e id, uint8_t div)
\brief set bclk divider
\param[in] id bclk id
\param[in] div divider ratio to set
*/
void CLOCK_setBclkDiv(BclkId_e id, uint8_t div);
/**
\fn void CLOCK_bclkEnable(BclkId_e id)
\brief enable bclk
\param[in] id bclk id
*/
void CLOCK_bclkEnable(BclkId_e id);
/**
\fn void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src)
\brief select mclk source
\param[in] id mclk id
\param[in] src clock source to set
*/
void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src);
/**
\fn void CLOCK_mclkEnable(MclkId_e id)
\brief mclk enable
\param[in] id mclk id
*/
void CLOCK_mclkEnable(MclkId_e id);
/**
\fn void CLOCK_mclkDisable(MclkId_e id)
\brief mclk disable
\param[in] id mclk id
*/
void CLOCK_mclkDisable(MclkId_e id);
/**
\fn void CLOCK_setMclkDiv(MclkId_e id, uint8_t div)
\brief set mclk divider
\param[in] id mclk id
\param[in] div divider ratio to set
*/
void CLOCK_setMclkDiv(MclkId_e id, uint8_t div);
/** \} */
/** \name HAL Driver declaration */
/* \{ */
extern int32_t GPR_setClockSrc(ClockId_e id, ClockSelect_e select);
extern int32_t GPR_setClockDiv(ClockId_e id, uint32_t div);
extern void GPR_clockEnable(ClockId_e id);
extern void GPR_clockDisable(ClockId_e id);
extern uint32_t GPR_getClockFreq(ClockId_e id);
extern void GPR_setFracDivConfig(FracDivConfig_t * config);
extern void GPR_fracDivOutCLkEnable(FracDivOutClkId_e id);
extern void GPR_fracDivOutClkDisable(FracDivOutClkId_e id);
extern void GPR_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div);
extern void GPR_setBclkSrc(BclkId_e id, BclkSrc_e src);
extern void GPR_setBclkDiv(BclkId_e id, uint8_t div);
extern void GPR_BclkEnable(BclkId_e id);
extern void GPR_setMclkSrc(MclkId_e id, MclkSrc_e src);
extern void GPR_mclkEnable(MclkId_e id);
extern void GPR_mclkDisable(MclkId_e id);
extern void GPR_setMclkDiv(MclkId_e id, uint8_t div);
extern void GPR_swReset(ClockResetId_e id);
extern void GPR_swResetModule(const ClockResetVector_t *v);
extern void GPR_initialize(void);
extern void GPR_setApbGprAcg( void );
extern void GPR_lockUpActionCtrl(bool enable);
extern uint32_t GPR_getCPLockUpResetCtrl(void);
extern ApRstSource_e GPR_apGetRstSrc(void);
extern CpRstSource_e GPR_cpGetRstSrc(void);
extern void GPR_cpResetCfgSet(bool wdtRstEn, bool sysRstApb, bool lockupRstEn, bool cpAPmuRst);
extern void GPR_setApbGprAcg( void );
extern void GPR_bootSetting( void );
void CLOCK_AssertChkBeforeSlp(void);
/** \} */
#ifdef __cplusplus
}
#endif
/** \}*/
#endif

View File

@@ -0,0 +1,44 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename:cpxip.h
*
* Description:
*
* History:
*
* Notes:
*
******************************************************************************/
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#ifndef CP_XIP_H
#define CP_XIP_H
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
void CPXIP_Enable(void);
uint8_t CPXIP_QSPI_Erase_Sector(uint32_t SectorAddress);
uint8_t CPXIP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
uint8_t CPXIP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
#endif

View File

@@ -0,0 +1,262 @@
#ifndef BSP_CSPI_H
#define BSP_CSPI_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
#define CSPI_TRANSFER_TRUNK_SIZE 7680 ///< Each DMA descriptor data size, fixed to 7680byte
typedef void (*cspiCbEvent_fn) (uint32_t event); ///< cspi callback event.
/** \brief CSPI flags */
#define CSPI_FLAG_INITIALIZED (1UL << 0) ///< CSPI initialized
#define CSPI_FLAG_POWERED (1UL << 1) ///< CSPI powered on
/** \brief CSPI DMA */
typedef struct
{
DmaInstance_e rxInstance; ///< Receive DMA instance number
int8_t rxCh; ///< Receive channel number
uint8_t rxReq; ///< Receive DMA request number
void (*rxCb)(uint32_t event); ///< Receive callback
DmaDescriptor_t *descriptor; ///< Rx descriptor
} cspiDma_t;
// CSPI PINS
typedef const struct
{
PIN *mclk; ///< Main clk Pin identifier
PIN *pclk; ///< Pixel clk Pin identifier
PIN *cs; ///< Cs Pin identifier
PIN *sdo0; ///< Din Pin identifier
PIN *sdo1; ///< Dout Pin identifier
} cspiPins_t;
typedef struct
{
uint8_t busy; ///< Transmitter/Receiver busy flag
} cspiRteStats_t;
typedef enum
{
CAM_8W = 10, ///< 8w use 10 dma descriptor chain
CAM_30W = 40, ///< 30w use 40 dma descriptor chain
}camResolution_e;
typedef enum
{
CAM_6_5_M = 0, ///< camera 6.5M HZ
CAM_13_M = 1, ///< camera 13M HZ
CAM_25_5_M = 2, ///< camera 25.5M HZ
CAM_24_M = 3, ///< camera 24M HZ
CAM_20_M = 4, ///< camera 20M HZ
}camFrequence_e;
// CSPI information (Run-time)
typedef struct
{
cspiCbEvent_fn cbEvent; ///< Event callback
cspiRteStats_t status; ///< CSPI status flags
uint8_t flags; ///< CSPI driver flags
uint32_t busSpeed; ///< CSPI bus speed
uint8_t dataWidth; ///< CSPI data bits select in unit of byte
uint32_t targetAddr; ///< CSPI target address
camResolution_e resolution; ///< Camera resolution
} cspiInfo_t;
// SPI Resources definition
typedef struct
{
CSPI_TypeDef *reg; ///< SPI register pointer
cspiPins_t pins; ///< SPI PINS configuration
cspiDma_t *dma; ///< SPI DMA configuration pointer
cspiInfo_t *info; ///< Run-Time Information
} cspiRes_t;
/**
\brief General power states
*/
typedef enum
{
CSPI_POWER_OFF, ///< Power off: no operation possible
CSPI_POWER_FULL ///< Power on: full operation at maximum performance
} cspiPowerState_e;
typedef struct
{
uint32_t slaveModeEn : 1; ///< Slave Mode Enable
uint32_t slotSize : 5; ///< Slot Size
uint32_t wordSize : 5; ///< Word Size
uint32_t alignMode : 1; ///< Align Mode
uint32_t endianMode : 1; ///< Endian Mode
uint32_t dataDly : 2; ///< Data Delay
uint32_t txPad : 2; ///< Tx padding
uint32_t rxSignExt : 1; ///< Rx Sign Entension
uint32_t txPack : 2; ///< Tx Pack
uint32_t rxPack : 2; ///< Rx Pack
uint32_t txFifoEndianMode : 1; ///< Tx Fifo Endian Mode
uint32_t rxFifoEndianMode : 1; ///< Rx Fifo Endian Mode
}cspiDataFmt_t;
typedef struct
{
uint32_t slotEn : 3; ///< Slot Enable
uint32_t slotNum : 8; ///< Slot Num
}cspiSlotCtrl_t;
typedef struct
{
uint32_t bclkPolarity : 1; ///< Bclk Polarity
uint32_t fsPolarity : 1; ///< Frame Synchronization Polarity
uint32_t fsWidth : 6; ///< Frame Synchronization Width
}cspiBclkFsCtrl_t;
typedef struct
{
uint32_t rxDmaReqEn : 1; ///< Rx Dma Req Enable
uint32_t txDmaReqEn : 1; ///< Tx Dma Req Enable
uint32_t rxDmaTimeOutEn : 1; ///< Rx Dma Timeout Enable
uint32_t dmaWorkWaitCycle : 5; ///< Dma Work Wait Cycle
uint32_t rxDmaBurstSizeSub1 : 4; ///< Rx Dma Burst Size subtract 1
uint32_t txDmaBurstSizeSub1 : 4; ///< Tx Dma Burst Size subtract 1
uint32_t rxDmaThreadHold : 4; ///< Rx Dma Threadhold
uint32_t txDmaThreadHold : 4; ///< Tx Dma Threadhold
uint32_t rxFifoFlush : 1; ///< Rx Fifo flush
uint32_t txFifoFlush : 1; ///< Tx Fifo flush
}cspiDmaCtrl_t;
typedef struct
{
uint32_t txUnderRunIntEn : 1; ///< Tx Underrun interrupt Enable
uint32_t txDmaErrIntEn : 1; ///< Tx Dma Err Interrupt Enable
uint32_t txDatIntEn : 1; ///< Tx Data Interrupt Enable
uint32_t rxOverFlowIntEn : 1; ///< Rx Overflow Interrupt Enable
uint32_t rxDmaErrIntEn : 1; ///< Rx Dma Err Interrupt Enable
uint32_t rxDatIntEn : 1; ///< Rx Data Interrupt Enable
uint32_t rxTimeOutIntEn : 1; ///< Rx Timeout Interrupt Enable
uint32_t fsErrIntEn : 1; ///< Frame Start Interrupt Enable
uint32_t frameStartIntEn : 1; ///< Frame End Interrupt Enable
uint32_t frameEndIntEn : 1; ///< Frame End Interrupt Enable
uint32_t cspiBusTimeOutIntEn : 1; ///< Not use
uint32_t txIntThreshHold : 4; ///< Tx Interrupt Threadhold
uint32_t rxIntThreshHold : 4; ///< Rx Interrupt Threadhold
}cspiIntCtrl_t;
typedef struct
{
uint32_t rxTimeOutCycle : 24; ///< Rx Timeout Cycle
}cspiTimeOutCycle_t;
typedef struct
{
uint32_t txUnderRun : 1; ///< Tx Underrun
uint32_t txDmaErr : 1; ///< Tx Dma Err
uint32_t txDataRdy : 1; ///< Tx Data ready, readOnly
uint32_t rxOverFlow : 1; ///< Rx OverFlow
uint32_t rxDmaErr : 1; ///< Rx Dma Err
uint32_t rxDataRdy : 1; ///< Rx Data ready, readOnly
uint32_t rxFifoTimeOut : 1; ///< Rx Fifo timeout
uint32_t fsErr : 4; ///< Frame synchronization Err
uint32_t frameStart : 1; ///< Frame start
uint32_t frameEnd : 1; ///< Frame end
uint32_t txFifoLevel : 6; ///< Tx Fifo Level, readOnly
uint32_t rxFifoLevel : 6; ///< Rx Fifo level, readOnly
uint32_t cspiBusTimeOut : 1; ///< Cspi Bus timeout
}cspiStats_t;
typedef struct
{
uint32_t enable : 1; ///< Enable
uint32_t csEn : 1; ///< CS signal check
uint32_t rxWid : 1; ///< Rx Width
uint32_t rxdSeq : 1; ///< Rx Sequence
uint32_t cpol : 1; ///< SPI polarity
uint32_t cpha : 1; ///< SPI phase
uint32_t frameProcEn : 1; ///< Frame Process Enable
uint32_t fillYonly : 1; ///< Fill Y Only
uint32_t hwInitEn : 1; ///< HW Init Enable
uint32_t lsCheckEn : 1; ///< Line Start Check Enable
uint32_t dpCheckEn : 1; ///< Data Pcket Check Enable
uint32_t frameProcInitEn : 1; ///< Frame Process Init Enable
uint32_t rowScaleRatio : 4; ///< Row Scale Ratio
uint32_t colScaleRatio : 4; ///< Column Scale Ratio
uint32_t scaleBytes : 2; ///< Scale Bytes
}cspiCtrl_t;
typedef struct
{
uint32_t autoCgEn : 1; ///< Auto Configure Enable
}cspiAutoCgCtrl_t;
typedef struct
{
uint32_t cspiBusTimeOutCycle : 24; ///< Cspi Bus Timeout Cycle
uint32_t dataId : 8; ///< Data Indication, readOnly
}cspiFrameInfo0_t;
typedef struct
{
uint32_t cspiInit : 1; ///< Cspi Init
}cspiInit_t;
/**
\brief Cspi control bits.
*/
#define CSPI_CTRL_TRANSABORT (1UL << 0) ///< CSPI trans abort
#define CSPI_CTRL_BUS_SPEED (1UL << 1) ///< CSPI trans abort
#define CSPI_CTRL_DATA_BITS (1UL << 2) ///< CSPI trans abort
#define CSPI_CTRL_DATA_FORMAT (1UL << 3) ///< CSPI data format
#define CSPI_CTRL_SLOT_CTRL (1UL << 4) ///< CSPI slot ctrl
#define CSPI_CTRL_BCLK_FS_CTRL (1UL << 5) ///< CSPI bclk fs ctrl
#define CSPI_CTRL_DMA_CTRL (1UL << 6) ///< CSPI dma ctrl
#define CSPI_CTRL_INT_CTRL (1UL << 7) ///< CSPI int ctrl
#define CSPI_CTRL_TIMEOUT_CYCLE (1UL << 8) ///< CSPI timeout cycle
#define CSPI_CTRL_STATUS (1UL << 9) ///< CSPI status
#define CSPI_CTRL_CSPICTL (1UL << 10) ///< CSPI control
#define CSPI_CTRL_AUTO_CG_CTRL (1UL << 11) ///< CSPI auto cg ctrl
#define CSPI_CTRL_FRAME_INFO0 (1UL << 12) ///< CSPI frame info0
#define CSPI_CTRL_INIT (1UL << 13) ///< CSPI init
#define CSPI_CTRL_RXTOR (1UL << 14) ///< CSPI rx timeout cycle
#define CSPI_CTRL_MEM_ADDR (1UL << 15) ///< CSPI memory addr set
#define CSPI_CTRL_FLUSH_RX_FIFO (1UL << 16) ///< Flush rx fifo
#define CSPI_CTRL_START_STOP (1UL << 17) ///< Start or stop cspi
#define CSPI_CTRL_RESOLUTION_SET (1UL << 18) ///< Camera resolution set
/**
\brief Access structure of the CSPI Driver.
*/
typedef struct
{
int32_t (*init) (cspiCbEvent_fn cb_event); ///< Initialize CSPI Interface.
int32_t (*deInit) (void); ///< De-initialize CSPI Interface.
int32_t (*powerCtrl) (cspiPowerState_e state); ///< Control CSPI Interface Power.
int32_t (*recv) (void); ///< Open dma to receive data.
int32_t (*ctrl) (uint32_t control, uint32_t arg); ///< Control CSPI Interface.
} const cspiDrvInterface_t;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,333 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: dma.h
* Description: EC618 dma controller driver header file
* History: Rev1.0 2018-08-08
*
****************************************************************************/
#ifndef _DMA_EC618_H
#define _DMA_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup dma_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief List of DMA source/target address increment control options */
typedef enum
{
DMA_ADDRESS_INCREMENT_NONE = 0, /**< Increment neither source or target address */
DMA_ADDRESS_INCREMENT_SOURCE = 1U, /**< Increment source address */
DMA_ADDRESS_INCREMENT_TARGET = 2U, /**< Increment target address */
DMA_ADDRESS_INCREMENT_BOTH = 3U, /**< Increment both source and target address */
} DmaAddressIncrement_e;
/** \brief List of DMA flow control options */
typedef enum
{
DMA_FLOW_CONTROL_NONE = 0U, /**< No flow control */
DMA_FLOW_CONTROL_SOURCE = 1U, /**< Only source */
DMA_FLOW_CONTROL_TARGET = 2U, /**< Only target */
} DmaFlowControl_e;
/** \brief List of DMA transfer data width in peripheral involved case */
typedef enum
{
DMA_DATA_WIDTH_NO_USE = 0, /**< Data width is set to 0 in memory to memory transfer */
DMA_DATA_WIDTH_ONE_BYTE = 1U, /**< Data widath is 1 byte in peripheral involved transfer */
DMA_DATA_WIDTH_TWO_BYTES = 2U, /**< Data widath is 2 bytes in peripheral involved transfer */
DMA_DATA_WIDTH_FOUR_BYTES = 3U, /**< Data widath is 4 bytes in peripheral involved transfer */
} DmaDataWidth_e;
/** \brief Maximum burst size of each data transfer */
typedef enum
{
DMA_BURST_4_BYTES = 0, /**< Burst size is set to reserved */
DMA_BURST_8_BYTES = 1U, /**< Burst size is set to 8 bytes */
DMA_BURST_16_BYTES = 2U, /**< Burst size is set to 16 bytes */
DMA_BURST_32_BYTES = 3U, /**< Burst size is set to 32 bytes */
DMA_BURST_64_BYTES = 4U, /**< Burst size is set to 64 bytes */
} DmaBurstSize_e;
/** \brief DMA transfer configuration structure */
typedef struct
{
void *sourceAddress; /**< Source address */
void *targetAddress; /**< Target address */
DmaFlowControl_e flowControl; /**< Flow control setting */
DmaAddressIncrement_e addressIncrement; /**< Address increment setting */
DmaDataWidth_e dataWidth; /**< Data width setting */
DmaBurstSize_e burstSize; /**< Burst size setting */
uint32_t totalLength; /**< Transfer length onetime, less than 8k bytes. In descriptor chain it means every transfer's size */
} DmaTransferConfig_t;
/** \brief DMA descriptor extra configuration structure for descriptor-chain mode */
typedef struct
{
void *nextDesriptorAddress; /**< Next descriptor address */
bool stopDecriptorFetch; /**< Indicate whether this is the last descriptor */
bool enableStartInterrupt; /**< Start interrupt control */
bool enableEndInterrupt; /**< End interrupt control */
} DmaExtraConfig_t;
/** \brief DMA descriptor structure */
typedef struct
{
uint32_t DAR; /**< DMA Descriptor Address */
uint32_t SAR; /**< DMA Source Address */
uint32_t TAR; /**< DMA Target Address */
uint32_t CMDR; /**< DMA Command */
} DmaDescriptor_t;
/** \brief List of DMA interrupt sources */
typedef enum
{
/** Stop interrupt enable, when enabled, interrupt is triggered after the channel stops */
DMA_STOP_INTERRUPT_ENABLE = (1U << 29U),
/** EOR interrupt enable, when enabled, interrupt is triggered on End-Of-Receive condition */
DMA_EOR_INTERRUPT_ENABLE = (1U << 28U),
/** Start interrupt enable, when enabled, interrupt is triggered as soon as descriptor is loaded, valid for descriptor-chain-mode */
DMA_START_INTERRUPT_ENABLE = (1U << 22U),
/** End interrupt enable, when enabled, interrupt is triggered when transfer length decrements to 0 */
DMA_END_INTERRUPT_ENABLE = (1U << 21U),
} DmaInterruptEnable_e;
/** \brief List of DMA available intances */
typedef enum
{
DMA_INSTANCE_AP,
DMA_INSTANCE_MP,
DMA_INSTANCE_MAX,
} DmaInstance_e;
/** DMA specific error codes */
#define ARM_DMA_ERROR_CHANNEL_ALLOC (ARM_DRIVER_ERROR_SPECIFIC - 1) /**< No free channel any more */
#define ARM_DMA_ERROR_CHANNEL_NOT_OPEN (ARM_DRIVER_ERROR_SPECIFIC - 2) /**< Specific channel not open */
#define ARM_DMA_ERROR_CHANNEL_NOT_STOPPED (ARM_DRIVER_ERROR_SPECIFIC - 3) /**< Specific channel not stopped */
#define ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED (ARM_DRIVER_ERROR_SPECIFIC - 4) /**< Address alignment check failure */
/** List of events reported to application */
#define DMA_EVENT_ERROR (1) /**< Bus error */
#define DMA_EVENT_START (2) /**< Descriptor load successfully */
#define DMA_EVENT_END (3) /**< Transaction end */
#define DMA_EVENT_EOR (4) /**< Receive EOR signal */
#define DMA_EVENT_STOP (5) /**< Channel has stopped */
/**
\brief Defines callback function prototype.
Callback function will be called in DMA interrupt service routine after a transaction is complete
\param event transaction event for the current transaction, application can get the tansaction
result from this paramter, available events: DMA_EVENT_ERROR, DMA_EVENT_START, DMA_EVENT_END, DMA_EVENT_EOR, DMA_EVENT_STOP
*/
typedef void (*dma_callback_t)(uint32_t event);
/** \brief timeout value when stopping channel */
#define DMA_STOP_TIMEOUT (5000U)
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
\fn void DMA_init(DmaInstance_e instance)
\brief Intialize DMA hareware and internal used structure, call this function before any other DMA APIs
*/
void DMA_init(DmaInstance_e instance);
/** \name DMA Channel operation API */
/** \{ */
/**
\fn int32_t DMA_openChannel(DmaInstance_e instance)
\brief Opens a DMA channel
\return Channel on successful allocate
ARM_DMA_ERROR_CHANNEL_ALLOC when no free channel is found
\note Caller shall check the return code
*/
int32_t DMA_openChannel(DmaInstance_e instance);
/**
\fn int32_t DMA_closeChannel(DmaInstance_e instance, uint32_t channel)
\brief Closes a DMA channel
\param[in] instance
\param[in] channel DMA channel number
\return ARM_DRIVER_OK if no error happens
ARM_DMA_ERROR_CHANNEL_NOT_OPEN when channel is not open
\note This API will call \ref DMA_stopChannel to stop channel first if channel is running before close
*/
int32_t DMA_closeChannel(DmaInstance_e instance, uint32_t channel);
/**
\fn void DMA_startChannel(DmaInstance_e instance, uint32_t channel)
\brief Activates the DMA channel
\param[in] instance
\param[in] channel DMA channel number
*/
void DMA_startChannel(DmaInstance_e instance, uint32_t channel);
/**
\fn int32_t DMA_stopChannel(uint32_t channel, bool waitForStop)
\brief Stops the DMA channel from running
\param[in] channel DMA channel number
\param[in] waitForStop whether to wait channel to fully stop or not
\return ARM_DRIVER_OK if stops successfully
ARM_DMA_ERROR_CHANNEL_NOT_STOPPED if channel fails to stop until timeout expires
\note staus and interrupt flags will be cleared in this function call
*/
int32_t DMA_stopChannel(DmaInstance_e instance, uint32_t channel, bool waitForStop);
/**
\fn void DMA_resetChannel(uint32_t channel)
\brief Put the DMA channel to reset state
\param[in] channel DMA channel number
\note Make sure DMA is stopped before calling this function
*/
void DMA_resetChannel(DmaInstance_e instance, uint32_t channel);
/**
\fn void DMA_rigisterChannelCallback(uint32_t channel, dma_callback_t callback)
\brief Registers a DMA callback
\param[in] channel DMA channel number
\param[in] callback Given by the application and will be called in DMA interrupt service routine
*/
void DMA_rigisterChannelCallback(DmaInstance_e instance, uint32_t channel, dma_callback_t callback);
/**
\fn void DMA_enableChannelInterrupts(uint32_t channel, uint32_t mask)
\brief Enables DMA interrupts
\param[in] channel DMA channel number
\param[in] mask Mask of interrupt source to be set, can be ORed by items list in \ref DmaInterruptEnable_e
\note In no-descriptor-fetch mode, all interrupt sources can be enabled by calling this API, however, in descritor-fetch
mode, only \ref DMA_STOP_INTERRUPT_ENABLE \ref DMA_EOR_INTERRUPT_ENABLE can be done by this function call,
the \ref DMA_START_INTERRUPT_ENABLE and \ref DMA_END_INTERRUPT_ENABLE is controlled by setting in \ref DmaExtraConfig_t respectively.
*/
void DMA_enableChannelInterrupts(DmaInstance_e instance, uint32_t channel, uint32_t mask);
/**
\fn void DMA_disableChannelInterrupts(uint32_t channel, uint32_t mask)
\brief Disables DMA interrupts
\param[in] channel DMA channel number
\param[in] mask Mask of interrupt source to be disabled, can be ORed by items list in \ref DmaInterruptEnable_e
\note In no-descriptor-fetch mode, all interrupt sources can be disabled by calling this API, however, in descritor-fetch
mode, only \ref DMA_STOP_INTERRUPT_ENABLE \ref DMA_EOR_INTERRUPT_ENABLE can be done by this function call ,
the \ref DMA_START_INTERRUPT_ENABLE and \ref DMA_END_INTERRUPT_ENABLE is controlled by setting in \ref DmaExtraConfig_t respectively.
*/
void DMA_disableChannelInterrupts(DmaInstance_e instance, uint32_t channel, uint32_t mask);
/**
\fn uint32_t DMA_getEnabledInterrupts(uint32_t channel)
\brief Gets current enabled DMA channel interrupts
\param[in] channel DMA channel number
\return The logical OR of members of the enumeration \ref DmaInterruptEnable_e
*/
uint32_t DMA_getEnabledInterrupts(DmaInstance_e instance, uint32_t channel);
/**
\fn uint32_t DMA_getChannelCount(uint32_t channel)
\brief Obtains courrent transferred data length of a transaction in unit of byte
\param[in] channel DMA channel number
\return Size of data has been transferred
\note In descritor-fetch mode, Start Interrupt shall be enabled by enableStartInterrupt setting in \ref DmaExtraConfig_t
so that driver can load total transfer number for calculation before transferring.
*/
uint32_t DMA_getChannelCount(DmaInstance_e instance, uint32_t channel);
/**
\fn void DMA_setChannelRequestSource(uint32_t channel, DmaRequestSource_e request)
\brief Configures DMA request source
\param[in] channel DMA channel number
\param[in] request DMA request binded to this channel
*/
void DMA_setChannelRequestSource(DmaInstance_e instance, uint32_t channel, DmaRequestSource_e request);
/** \} */
/** \name DMA register mode API */
/** \{ */
/**
\fn void DMA_transferSetup(DmaInstance_e instance, uint32_t channel, const DmaTransferConfig_t* config)
\brief Setups DMA channel according to user's transfer configuration, usded for register mode
\param[in] instance
\param[in] channel DMA channel number
\param[in] config Pointer to transfer configuration
\note user configuration shall be retaining(global variable) for it will be used again after exit from low power
*/
void DMA_transferSetup(DmaInstance_e instance, uint32_t channel, const DmaTransferConfig_t* config);
/** \} */
/** \name DMA descriptor chain mode API */
/** \{ */
/**
\fn void DMA_buildDescriptor(DmaDescriptor_t* descriptor, const DmaTransferConfig_t* config, const DmaExtraConfig_t* extraConfig)
\brief Builds a descritor for DMA mode use
\param[out] descriptor Pointer to DMA descriptor instance
\param[in] config Pointer to transfer configuration
\param[in] extraConfig Pointer to extra configuration which is invalid in descriptor-chain-mode only
\note descriptor shall be retaining(global variable) for it will be used again after exit from low power
*/
void DMA_buildDescriptor(DmaDescriptor_t* descriptor, const DmaTransferConfig_t* config, const DmaExtraConfig_t* extraConfig);
/**
\fn void DMA_buildDescriptorChain(DmaDescriptor_t* descriptorArray, const DmaTransferConfig_t* config, const uint16_t chainCnt)
\brief Builds a descritor for DMA chain mode use
\param[out] descriptorArray Pointer to DMA descriptor chain array, should aligned with 16byte
\param[in] config Pointer to transfer configuration
\param[in] chainCnt The count of descriptor chain
\param[in] needStop Need cycling transfer data or not
\note descriptor shall be retaining(global variable) for it will be used again after exit from low power
*/
void DMA_buildDescriptorChain(DmaDescriptor_t* descriptorArray, const DmaTransferConfig_t* config, const uint16_t chainCnt, bool needStop);
/**
\fn int32_t DMA_loadChannelFirstDescriptor(DmaInstance_e instance, uint32_t channel, void* descriptorAddress)
\brief Loads first descritor
\param[in] instance
\param[in] channel DMA channel number
\param[in] descriptorAddress Address of descriptor from which to load, shall be aligend on a 16-byte boundary in memory
\return ARM_DRIVER_OK if success
ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED on address alignment check failure
*/
int32_t DMA_loadChannelFirstDescriptor(DmaInstance_e instance, uint32_t channel, void* descriptorAddress);
/**
\fn void DMA_loadChannelDescriptorAndRun(DmaInstance_e instance, uint32_t channel, void* descriptorAddress)
\brief Loads first descritor and run
\param[in] instance
\param[in] channel DMA channel number
\param[in] descriptorAddress Address of descriptor from which to load, shall be aligend on a 16-byte boundary in memory
\return ARM_DRIVER_OK if success
ARM_DMA_ERROR_ADDRESS_NOT_ALIGNED on address alignment check failure
*/
void DMA_loadChannelDescriptorAndRun(DmaInstance_e instance, uint32_t channel, void* descriptorAddress);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename:flash_rt.h
*
* Description:EC618 flash header file
*
* History:
*
* Notes:
*
******************************************************************************/
#ifndef _FLASH_EC618_RT_H
#define _FLASH_EC618_RT_H
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
/* QSPI Error codes */
#define QSPI_OK ((uint8_t)0x00)
#define QSPI_ERROR ((uint8_t)0x01)
#define QSPI_BUSY ((uint8_t)0x02)
#define QSPI_NOT_SUPPORTED ((uint8_t)0x04)
#define QSPI_SUSPENDED ((uint8_t)0x08)
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
typedef enum
{
QSPI_OP_ERASE = 0,
QSPI_OP_WRITE,
}QSPI_OpType_e;
/**
\brief definition of the flash operation callback, register using BSP_QSPI_Reg_Operation_Cb
call when flash erase and write happens.
\param[in] result the QSPI Error codes, listed above
\param[in] type to indicate erase or write
\param[in] address operation address
\param[in] size operation size
\return null
*/
typedef void (*BSP_QSPI_OperCallback_t)(uint8_t result, QSPI_OpType_e type, uint32_t address, uint32_t size);
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
uint8_t BSP_QSPI_Cfg_Gran_Size(uint16_t WriteGranSize);
uint8_t BSP_QSPI_Erase_Safe(uint32_t SectorAddress, uint32_t Size);
uint8_t BSP_QSPI_Write_Safe(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
uint8_t BSP_QSPI_Read_Safe(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
/**
\fn void BSP_QSPI_Reg_Operation_Cb(BSP_QSPI_OperCallback_t cb);
\brief register a user callback to get flash operation info. No time consuming operation allowed in this callback.
*/
void BSP_QSPI_Reg_Operation_Cb(BSP_QSPI_OperCallback_t cb);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,192 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: gpio.h
* Description: EC618 gpio driver header file
* History:
*
****************************************************************************/
#ifndef _GPIO_EC618_H
#define _GPIO_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup gpio_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief GPIO pin direction */
typedef enum
{
GPIO_DIRECTION_INPUT = 0U, /**< Set pin as input */
GPIO_DIRECTION_OUTPUT = 1U, /**< Set pin as output */
} GpioPinDirection_e;
/** \brief GPIO pin interrupt configuration */
typedef enum
{
GPIO_INTERRUPT_DISABLED = 0U, /**< Disable interrupt */
GPIO_INTERRUPT_LOW_LEVEL = 1U, /**< Low-level interrupt */
GPIO_INTERRUPT_HIGH_LEVEL = 2U, /**< High-level interrupt */
GPIO_INTERRUPT_FALLING_EDGE = 3U, /**< Falling edge interrupt */
GPIO_INTERRUPT_RISING_EDGE = 4U, /**< Rising edge interrupt */
} GpioInterruptConfig_e;
/** \brief GPIO pin configuration structure */
typedef struct
{
GpioPinDirection_e pinDirection; /**< GPIO direction, input or output */
union
{
GpioInterruptConfig_e interruptConfig; /**< Pin's interrupt configuration, valid when pinDirection is input */
uint32_t initOutput; /**< Initial pin output value, valid when pinDirection is output*/
} misc;
} GpioPinConfig_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name GPIO Driver Initialization */
/** \{ */
/**
\fn void GPIO_driverInit(void);
\brief Intialize GPIO driver internal data
\note It is not necessarty to call this function before using GPIO driver since it has been
called in \ref GPIO_pinConfig() api.
*/
void GPIO_driverInit(void);
/**
\fn void GPIO_driverDeInit(void);
\brief De-Intialize GPIO driver, disable GPIO clock and perform some clearups
*/
void GPIO_driverDeInit(void);
/** \} */
/** \name GPIO Configuration */
/** \{ */
/**
\fn void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config);
\brief Configure a GPIO pin
\param[in] port GPIO number (0, 1, ...)
\param[in] pin GPIO pin number
\param[in] config Pointer to GPIO pin configuration
*/
void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config);
/**
\fn void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config);
\brief Configure a GPIO pin's interrupt type(valid when this pin has been set as input)
\param[in] port GPIO number (0, 1, ...)
\param[in] pin GPIO pin number
\param[in] config GPIO interrupt configuration
*/
void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config);
/** \} */
/** \name GPIO Output Operations */
/** \{ */
/**
\fn void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output);
\brief Sets output level of multiple GPIO pins to logic 1 or 0
\code
Example to set bits[15,1:0] to 1 and clear bits[12:11, 7:6]
// pinMask shall be b10011000 11000011 = 0x98C3
// output shall be b10000000 00000011 = 0x8003
GPIO_pinWrite(0, 0x98C3, 0x8003);
// To set a single pin, let's say, pin 12 of GPIO0
GPIO_pinWrite(0, 1 << 12, 1 << 12);
// To clear a single pin, let's say, pin 12 of GPIO0
GPIO_pinWrite(0, 1 << 12, 0);
\endcode
\param[in] port GPIO number (0, 1, ...)
\param[in] pinMask GPIO pin mask to set
\param[in] output GPIO pin output logic level.
- 0: corresponding pin output low-logic level.
- 1: corresponding pin output high-logic level.
*/
void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output);
/** \} */
/** \name GPIO Input Operations */
/** \{ */
/**
\fn uint32_t GPIO_pinRead(uint32_t port, uint16_t pin)
\brief Reads current input value of GPIO specific pin
\param[in] port GPIO number (0, 1, ...)
\param[in] pin GPIO pin number
\return GPIO corresponding pin input value
*/
uint32_t GPIO_pinRead(uint32_t port, uint16_t pin);
/** \} */
/** \name GPIO Interrupt */
/** \{ */
/**
\fn uint16_t GPIO_getInterruptFlags(uint32_t port)
\brief Reads GPIO port interrupt status flags
\param[in] port GPIO number (0, 1, ...)
\return current GPIO interrupt status flag
*/
uint16_t GPIO_getInterruptFlags(uint32_t port);
/**
\fn void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask)
\brief Clears multiple GPIO pin interrupt status flags
\param[in] port GPIO number (0, 1, ...)
\param[in] mask GPIO pin number macro
*/
void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask);
/**
\fn uint16_t GPIO_saveAndSetIrqMask(uint32_t port)
\brief Reads GPIO port interrupt enable mask and diables whole port interrupts
\param[in] port GPIO number (0, 1, ...)
\return current GPIO port interrupt enable mask
\note Used in GPIO ISR to disable GPIO interrupts temporarily
*/
uint16_t GPIO_saveAndSetIrqMask(uint32_t port);
/**
\fn void GPIO_restoreIrqMask(uint32_t port, uint16_t mask)
\brief Restore GPIO port interrupt enable setting
\param[in] port GPIO number (0, 1, ...)
\param[in] mask GPIO interrupt enable mask
\note Used in GPIO ISR to restore GPIO enable setting upon exit
*/
void GPIO_restoreIrqMask(uint32_t port, uint16_t mask);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _GPIO_EC618_H */

View File

@@ -0,0 +1,310 @@
#define RMI_GPR_TOP_CLKEN_REG_INDEX (0)
#define RMI_GPR_XPSYS_CLKEN_REG_INDEX (1)
#define APB_GPR_TOP_MP_CLKEN_REG_INDEX (2)
#define APB_GPR_TOP_AP_CLKEN_REG_INDEX (3)
#define APB_GPR_APB_MP_PCLK_EN_REG_INDEX (4)
#define APB_GPR_APB_AP_PCLK_EN_REG_INDEX (5)
#define APB_GPR_APB_MP_FCLK_EN_REG_INDEX (6)
#define APB_GPR_APB_AP_FCLK_EN_REG_INDEX (7)
#define APB_GPR_TOP_ALL_CLKEN_REG_INDEX (8)
#define CLKEN_REG_INDEX_MAX (0xF)
/**
|-----registerAccessIndex-----|-----bitPosition-----|---------index---------|
|------------4 bit------------|--------5 bit--------|---------8 bit---------|
*/
#define CONSTRUCT_CLOCK_ID(registerAccessIndex, bitPosition, index) \
(((registerAccessIndex) << 13) | ((bitPosition) << 8) | (index))
/** Macro to extract index from clock id value */
#define GET_INDEX_FROM_CLOCK_ID(value) ((value) & 0xFFU)
/** Macro to extract bitPosition from clock id value */
#define GET_BP_FROM_CLOCK_ID(value) ((value >> 8U) & 0x1FU)
/** Macro to extract registerAccessIndex from clock id value */
#define GET_RAI_FROM_CLOCK_ID(value) ((value >> 13U) & 0xFU)
/**
|-----clockIdIndex-----|-----value-----|-----parentClockId-----|
|---------8 bit--------|-----4 bit-----|--------17 bit---------|
*/
/** Macro to compose clock select value */
#define MAKE_CLOCK_SEL_VALUE(clockIdIndex, value, parentClockId) \
((clockIdIndex << 21U) | value << 17U | parentClockId)
/** Macro to extract clockId from clock select value */
#define GET_CLOCKIDINDEX_FROM_CLOCK_SEL_VALUE(value) ((value >> 21U) & 0xFFUL)
/** Macro to extract value from clock select value */
#define GET_VALUE_FROM_CLOCK_SEL_VALUE(value) ((value >> 17U) & 0xFUL)
/** Macro to extract parentClockId from clock select value */
#define GET_PARENTCLOCKID_FROM_CLOCK_SEL_VALUE(value) (value & 0x1FFFFUL)
#define APB_GPR_TOP_AP_RST_REQ_REG_INDEX (0)
#define APB_GPR_APB_MP_PRST_REQ_REG_INDEX (1)
#define APB_GPR_APB_AP_PRST_REQ_REG_INDEX (2)
#define APB_GPR_APB_MP_FRST_REQ_REG_INDEX (3)
#define APB_GPR_APB_AP_FRST_REQ_REG_INDEX (4)
#define RMI_GPR_TOP_RSTREQ_REG_INDEX (5)
#define RMI_GPR_XPSYS_RSTREQ_REG_INDEX (6)
/**
|-----registerAccessIndex-----|-----bitPosition-----|
|------------4 bit------------|--------8 bit--------|
*/
#define CONSTRUCT_CLOCK_RESET_ID(registerAccessIndex, bitPosition) \
(((registerAccessIndex) << 8) | (bitPosition))
/** Macro to extract bitPosition from clock reset id value */
#define GET_BP_FROM_CLOCK_RESET_ID(value) ((value) & 0xFFU)
/** Macro to extract registerAccessIndex from clock reset id value */
#define GET_RAI_FROM_CLOCK_RESET_ID(value) ((value >> 8U) & 0xFU)
/** \brief List of IDs used for sw reset control */
typedef enum
{
/* Top AP Reset */
RST_AP_FABSYS_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 0), /**< Ap fab sys AHB reset */
RST_AP_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 1), /**< Ap RMI AHB reset */
RST_MFAB_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 2), /**< MFAB AHB reset */
RST_AFBBR_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 3), /**< AFBBR AHB reset */
RST_CFBBR_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 4), /**< CFBBR AHB reset */
RST_MSMB_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 5), /**< MSMB AHB reset */
RST_FLASH_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 6), /**< Flash AHB reset */
RST_PSRAM_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 7), /**< Psram AHB reset */
RST_ULOG_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 8), /**< Unilog AHB reset */
RST_USBC_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 9), /**< Usbc AHB reset */
RST_CLK_FLASH = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 10), /**< Flash Func reset */
RST_CLK_PSRAM = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 11), /**< Psram Func reset */
RST_AONIF = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 12), /**< Aonif reset */
RST_LPUA = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 13), /**< Lpua reset */
RST_CLK_FRACDIV = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 14), /**< Fracdiv reset */
RST_ULOG_SMP = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 15), /**< Unilog Smp reset */
RST_FCLK_FUSE = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 16), /**< Fuse Func reset */
RST_UTFC_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 17), /**< UTfc AHB reset */
RST_ULDP_HCLK = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 18), /**< Uldp AHB reset */
// reserved = 19~26,
RST_USBC_PHY = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 27), /**< Usbc PHY reset */
RST_USBP_POR = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 28), /**< USBP Por reset */
RST_USBP_UTMI = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_TOP_AP_RST_REQ_REG_INDEX, 29), /**< USBP Utmi reset */
/* APB MP Reset */
// reserved = 0,
RST_PCLK_SIPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 1), /**< Sipc APB reset */
RST_PCLK_AON = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 2), /**< Aon APB reset */
RST_PCLK_CPMU = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 3), /**< Cpmu APB reset */
RST_PCLK_PMDIG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 4), /**< Pmdig APBreset */
RST_PCLK_RFDIG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 5), /**< Rfdig APB reset */
RST_PCLK_PAD = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 6), /**< Pad APB reset */
RST_PCLK_GPIO = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 7), /**< Gpio APB reset */
RST_PCLK_FUSE = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 8), /**< Fuse APB reset */
RST_PCLK_TRNG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 9), /**< Trng APB reset */
RST_PCLK_USBP = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 10), /**< Usbp APB reset */
RST_PCLK_LPUC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 11), /**< Lpuc APB reset */
RST_PCLK_UART0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 12), /**< Uart0 APB reset */
RST_PCLK_UART1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 13), /**< Uart1 APB reset */
RST_PCLK_UART2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 14), /**< Uart2 APB reset */
RST_PCLK_SPI0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 15), /**< Ssp 0 APB reset */
RST_PCLK_SPI1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 16), /**< Ssp 1 APB reset */
RST_PCLK_I2S0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 17), /**< I2s 0 APB reset */
RST_PCLK_I2S1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_PRST_REQ_REG_INDEX, 18), /**< I2s 1 APB reset */
/* APB AP Reset */
RST_PCLK_WDG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 0), /**< WDG APB reset */
RST_PCLK_TIMER0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 1), /**< Timer0 APB reset */
RST_PCLK_TIMER1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 2), /**< Timer1 APBreset */
RST_PCLK_TIMER2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 3), /**< Timer2 APB reset */
RST_PCLK_TIMER3 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 4), /**< Timer3 APB reset */
RST_PCLK_TIMER4 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 5), /**< Timer4 APB reset */
RST_PCLK_TIMER5 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 6), /**< Timer5 APB reset */
RST_PCLK_IPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 7), /**< IPC APB reset */
RST_PCLK_I2C0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 8), /**< I2C0 APB reset */
RST_PCLK_I2C1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 9), /**< I2C1 APB reset */
RST_PCLK_USIM0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 10), /**< USIM0 APB reset */
RST_PCLK_USIM1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 11), /**< USIM1 APB reset */
RST_PCLK_KPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 12), /**< KPC APB reset */
RST_PCLK_ONEW = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_PRST_REQ_REG_INDEX, 13), /**< ONEW APB reset */
/* APB MP Func Reset */
RST_FCLK_UART0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 0), /**< Uart0 Func reset */
RST_FCLK_UART1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 1), /**< Uart1 Func reset */
RST_FCLK_UART2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 2), /**< Uart2 Func reset */
RST_FCLK_SPI0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 3), /**< SSP0 Func reset */
RST_FCLK_SPI1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 4), /**< SSP1 Func reset */
RST_FCLK_I2S0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 5), /**< I2S0 Func reset */
RST_FCLK_I2S1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_MP_FRST_REQ_REG_INDEX, 6), /**< I2S1 Func reset */
/* APB AP Func Reset */
RST_FCLK_WDG = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 0), /**< WDG Func reset */
RST_FCLK_TIMER0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 1), /**< TIMER0 Func reset */
RST_FCLK_TIMER1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 2), /**< TIMER1 Func reset */
RST_FCLK_TIMER2 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 3), /**< TIMER2 Func reset */
RST_FCLK_TIMER3 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 4), /**< TIMER3 Func reset */
RST_FCLK_TIMER4 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 5), /**< TIMER4 Func reset */
RST_FCLK_TIMER5 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 6), /**< TIMER5 Func reset */
RST_FCLK_I2C0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 7), /**< I2C0 Func reset */
RST_FCLK_I2C1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 8), /**< I2C1 Func reset */
RST_FCLK_USIM0 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 9), /**< USIM0 Func reset */
RST_FCLK_USIM1 = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 10), /**< USIM1 Func reset */
RST_FCLK_KPC = CONSTRUCT_CLOCK_RESET_ID(APB_GPR_APB_AP_FRST_REQ_REG_INDEX, 11), /**< KPC Func reset */
/* RMI TOP Reset */
RST_TOP_PBRG_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 0), /**< DMA AHB domain reset */
RST_TOP_PBRG_PCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 1), /**< DMA APB domain reset */
RST_TOP_GPR_PCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_TOP_RSTREQ_REG_INDEX, 2), /**< GPR APB domain reset */
/* RMI XPSYS Reset */
RST_CACHE_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 0), /**< GPR CACHE AHB domain reset */
RST_FABSUB_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 1), /**< GPR FABSUB AHB domain reset */
RST_SBU_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 2), /**< GPR SBU AHB domain reset */
RST_PBRG_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 3), /**< GPR PDMA AHB domain reset */
RST_SPIS_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 4), /**< GPR SPIS AHB domain reset */
RST_XIC_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 5), /**< GPR XIC AHB domain reset */
RST_ULOG_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 6), /**< GPR ULOG AHB domain reset */
RST_TMU_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 7), /**< GPR TMU AHB domain reset */
RST_SCT_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 8), /**< GPR SCT AHB domain reset */
RST_UTFC_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 11), /**< GPR UTFC AHB domain reset */
RST_ULDP_RMI_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 12), /**< GPR ULDP AHB domain reset */
RST_SCT_HCLK = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 13), /**< GPR SCT AHB reset */
RST_PCLK_DMA = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 15), /**< GPR PDMA APB reset */
RST_TMU_SMP = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 16), /**< GPR TMU SMP reset */
RST_TMU_CLKCAL = CONSTRUCT_CLOCK_RESET_ID(RMI_GPR_XPSYS_RSTREQ_REG_INDEX, 17), /**< GPR TMU CLKCAL reset */
} ClockResetId_e;
/** \brief typedef for reset whole module */
typedef struct
{
uint32_t idNumber; /**< number of ids this module contains */
uint32_t delayCpuCycles; /**< the cycles need to delay after release */
const ClockResetId_e* resetReleaseQueue; /**< pointer to the queue(array) of ids, reset & release operation sequence
depends on the position of id in the array, so arrange it properly */
} ClockResetVector_t;
#define RESET_RELEASE_DELAY_US (204)
#define MAKE_RESET_VECTOR(delay, ...) \
{ \
(sizeof((ClockResetId_e [])__VA_ARGS__) / sizeof(ClockResetId_e)), \
(delay), \
(const ClockResetId_e [])__VA_ARGS__ \
}
#define RESET_VECTOR_PTR(v) ((ClockResetVector_t [])v)
#define UART0_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART0, RST_FCLK_UART0, RST_PCLK_UART0, RST_FCLK_UART0})
#define UART1_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART1, RST_FCLK_UART1, RST_PCLK_UART1, RST_FCLK_UART1})
#define UART2_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_UART2, RST_FCLK_UART2, RST_PCLK_UART2, RST_FCLK_UART2})
#define SPI0_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_SPI0, RST_FCLK_SPI0, RST_PCLK_SPI0, RST_FCLK_SPI0})
#define SPI1_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_SPI1, RST_FCLK_SPI1, RST_PCLK_SPI1, RST_FCLK_SPI1})
#define KPC_RESET_VECTOR MAKE_RESET_VECTOR(RESET_RELEASE_DELAY_US, {RST_PCLK_KPC, RST_FCLK_KPC, RST_PCLK_KPC, RST_FCLK_KPC})
typedef enum
{
FRACDIV_ROOT_CLK_26M,
FRACDIC_ROOT_CLK_408M
} FracDivRootClk_e;
typedef struct
{
FracDivRootClk_e source;
uint32_t fracDiv0DivRatioInteger;
uint32_t fracDiv0DivRatioFrac;
uint32_t fracDiv1DivRatioInteger;
uint32_t fracDiv1DivRatioFrac;
} FracDivConfig_t;
typedef enum
{
FRACDIV0_OUT0,
FRACDIV0_OUT1,
FRACDIV0_OUT2,
FRACDIV0_OUT3,
FRACDIV1_OUT0,
FRACDIV1_OUT1,
FRACDIV1_OUT2,
FRACDIV1_OUT3
} FracDivOutClkId_e;
typedef enum
{
BCLK0,
BCLK1
} BclkId_e;
typedef enum
{
MCLK0,
MCLK1,
MCLK2
} MclkId_e;
typedef enum
{
BCLK_SRC_FRACDIV0_OUT0 = 1,
BCLK_SRC_FRACDIV0_OUT1 = 2,
BCLK_SRC_FRACDIV0_OUT2 = 3,
BCLK_SRC_FRACDIV0_OUT3 = 4,
BCLK_SRC_FRACDIV1_OUT0 = 5,
BCLK_SRC_FRACDIV1_OUT1 = 6,
BCLK_SRC_FRACDIV1_OUT2 = 7,
BCLK_SRC_FRACDIV1_OUT3 = 8,
BCLK_SRC_CLK_MFG = 9,
BCLK_SRC_19P2M = 10
} BclkSrc_e;
typedef enum
{
MCLK_SRC_FRACDIV0_OUT0 = 1,
MCLK_SRC_FRACDIV0_OUT1 = 2,
MCLK_SRC_FRACDIV0_OUT2 = 3,
MCLK_SRC_FRACDIV0_OUT3 = 4,
MCLK_SRC_FRACDIV1_OUT0 = 5,
MCLK_SRC_FRACDIV1_OUT1 = 6,
MCLK_SRC_FRACDIV1_OUT2 = 7,
MCLK_SRC_FRACDIV1_OUT3 = 8,
MCLK_SRC_CLK_MFG = 9,
MCLK_SRC_19P2M = 10,
MCLK_SRC_CLK_SMP = 11,
MCLK_SRC_CLK_USBP_12M = 12,
MCLK_SRC_CLK_USBP_48M = 13,
MCLK_SRC_CLK_USBC_PHY = 14,
} MclkSrc_e;
typedef enum
{
GPR_APRST_SWRST = 0,
GPR_APRST_WDG,
GPR_APRST_LOCKUP,
GPR_APRST_INVALID,
}ApRstSource_e;
typedef enum
{
GPR_CPRST_SWRST = 0,
GPR_CPRST_WDG,
GPR_CPRST_LOCKUP,
GPR_CPRST_INVALID,
}CpRstSource_e;

View File

@@ -0,0 +1,319 @@
#ifndef BSP_I2S_H
#define BSP_I2S_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
#include "hal_i2s.h" // To use some of typedef in this H file and the macro of DMA_CHAIN_NUM(can dynamic array in C99?)
#define POLLING_MODE 0x1
#define DMA_MODE 0x2
//////////////////////////////////////////////////////////////////////////////////////////////
// I2S Setting field Start
// All the I2S's parameters that need user to set are all put here
//////////////////////////////////////////////////////////////////////////////////////////////
#define ES8388_IICADDR 0x11
#define NAU88C22_IICADDR 0x1A
#define ES8311_IICADDR 0x18
// Sample rate that 618 supports
#define SAMPLE_RATE_8K 0x1
#define SAMPLE_RATE_16K 0x2
#define SAMPLE_RATE_32K 0x3
#define SAMPLE_RATE_22_05K 0x4
#define SAMPLE_RATE_44_1K 0x5
#define SAMPLE_RATE_48K 0x6
#define SAMPLE_RATE_96K 0x7
// I2S0 Configuration
#define RTE_I2S0 1
#define RTE_I2S0_IO_MODE DMA_MODE
#define RTE_I2S0_MCLK_PAD_ADDR 39
#define RTE_I2S0_MCLK_FUNC PAD_MUX_ALT1
#define RTE_I2S0_BCLK_PAD_ADDR 35
#define RTE_I2S0_BCLK_FUNC PAD_MUX_ALT1
#define RTE_I2S0_LRCK_PAD_ADDR 36
#define RTE_I2S0_LRCK_FUNC PAD_MUX_ALT1
#define RTE_I2S0_DIN_PAD_ADDR 37
#define RTE_I2S0_DIN_FUNC PAD_MUX_ALT1
#define RTE_I2S0_DOUT_PAD_ADDR 38
#define RTE_I2S0_DOUT_FUNC PAD_MUX_ALT1
// I2S1 Configuration
#define RTE_I2S1 0
#define RTE_I2S1_IO_MODE DMA_MODE
#define RTE_I2S1_MCLK_PAD_ADDR 18
#define RTE_I2S1_MCLK_FUNC PAD_MUX_ALT1
#define RTE_I2S1_BCLK_PAD_ADDR 19
#define RTE_I2S1_BCLK_FUNC PAD_MUX_ALT1
#define RTE_I2S1_LRCK_PAD_ADDR 20
#define RTE_I2S1_LRCK_FUNC PAD_MUX_ALT1
#define RTE_I2S1_DIN_PAD_ADDR 21
#define RTE_I2S1_DIN_FUNC PAD_MUX_ALT1
#define RTE_I2S1_DOUT_PAD_ADDR 22
#define RTE_I2S1_DOUT_FUNC PAD_MUX_ALT1
//////////////////////////////////////////////////////////////////////////////////////////////
// I2S Setting field End
//////////////////////////////////////////////////////////////////////////////////////////////
/****** I2S Event *****/
#define I2S_EVENT_TRANSFER_COMPLETE (1UL << 0) // Data Transfer completed
#define I2S_EVENT_DATA_LOST (1UL << 1) // Data lost: Receive overflow / Transmit underflow
#define I2S_EVENT_MODE_FAULT (1UL << 2) // Master Mode Fault (SS deactivated when Master)
// DMA I2S0 Request ID
#define RTE_I2S0_DMA_TX_REQID DMA_REQUEST_I2S0_TX
#define RTE_I2S0_DMA_RX_REQID DMA_REQUEST_I2S0_RX
// DMA I2S1 Request ID
#define RTE_I2S1_DMA_TX_REQID DMA_REQUEST_I2S1_TX
#define RTE_I2S1_DMA_RX_REQID DMA_REQUEST_I2S1_RX
typedef void (*i2sCbEvent_fn) (uint32_t event, uint32_t arg); // i2s callback event.
// I2S IRQ
typedef struct
{
IRQn_Type irqNum; // I2S IRQ Number
IRQ_Callback_t cbIrq;
} i2sIrq_t;
// I2S DMA
typedef struct
{
DmaInstance_e txInstance; // Transmit DMA instance number
int8_t txCh; // Transmit channel number
uint8_t txReq; // Transmit DMA request number
void (*txCb)(uint32_t event); // Transmit callback
DmaDescriptor_t *txDescriptor; // Tx descriptor
DmaInstance_e rxInstance; // Receive DMA instance number
int8_t rxCh; // Receive channel number
uint8_t rxReq; // Receive DMA request number
void (*rxCb)(uint32_t event); // Receive callback
DmaDescriptor_t *rxDescriptor; // Rx descriptor
} i2sDma_t;
// I2S PINS
typedef const struct
{
PIN *mclk; // main clk Pin identifier
PIN *bclk; // pixel clk Pin identifier
PIN *lrck; // cs Pin identifier
PIN *din; // din Pin identifier
PIN *dout; // dout Pin identifier
} i2sPins_t;
typedef struct
{
uint8_t busy; // Transmitter/Receiver busy flag
uint8_t dataLost; // Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint8_t modeFault; // Mode fault detected; optional (cleared on start of transfer operation)
} i2sStatus_t;
// I2S Transfer Information (Run-Time)
typedef struct
{
uint32_t num; // Total number of transfers
uint8_t *rxBuf; // Pointer to in data buffer
uint8_t *txBuf; // Pointer to out data buffer
uint32_t rxCnt; // Number of data received
uint32_t txCnt; // Number of data sent
uint32_t dumpVal; // Variable for dumping DMA data
uint16_t defVal; // Default transfer value
} i2sTransferInfo_t;
// I2S information (Run-time)
typedef struct
{
i2sCbEvent_fn txCbEvent; // tx event callback
i2sCbEvent_fn rxCbEvent; // rx event callback
uint32_t mode; // I2S mode
uint32_t busSpeed; // I2S bus speed
uint16_t chainCnt;
uint32_t totalNum; // Total length of audio source
} i2sInfo_t;
// I2S Resources definition
typedef struct
{
I2S_TypeDef *reg; // I2S register pointer
i2sPins_t pins; // I2S PINS configuration
i2sDma_t *dma; // I2S DMA configuration pointer
i2sIrq_t *irq; // I2S IRQ configuration pointer
i2sInfo_t *info; // Run-Time Information
} i2sResources_t;
/**
\brief General power states
*/
typedef enum
{
I2S_POWER_OFF, // Power off: no operation possible
I2S_POWER_FULL // Power on: full operation at maximum performance
} i2sPowerState_e;
/**
\brief Access structure of the I2S Driver.
*/
typedef struct
{
int32_t (*init) (i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent); // Initialize I2S Interface.
int32_t (*deInit) (void); // De-initialize I2S Interface.
int32_t (*powerCtrl) (i2sPowerState_e state); // Control I2S Interface Power.
int32_t (*send) (void *data, uint32_t chunkNum); // Start sending data from I2S Interface.
int32_t (*recv) (void *data, uint32_t chunkNum); // Start receiving data from I2S Interface.
int32_t (*ctrl) (uint32_t control, uint32_t arg); // Control I2S Interface.
uint32_t (*getTotalCnt) (void);
} const i2sDrvInterface_t;
typedef struct
{
uint32_t slaveModeEn : 1; // Slave Mode Enable
uint32_t slotSize : 5; // Slot Size
uint32_t wordSize : 5; // Word Size
uint32_t alignMode : 1; // Align Mode
uint32_t endianMode : 1; // Endian Mode
uint32_t dataDly : 2; // Data Delay
uint32_t txPad : 2; // Tx Padding
uint32_t rxSignExt : 1; // Rx Sign extention
uint32_t txPack : 2; // Tx Pack
uint32_t rxPack : 2; // Rx Pack
uint32_t txFifoEndianMode : 1; // Tx Fifo Endian Mode
uint32_t rxFifoEndianMode : 1; // Rx Fifo Endian Mode
}i2sDataFmt_t;
/** \brief I2S Slot Control */
typedef struct
{
uint32_t slotEn : 8; // Slot Enable
uint32_t slotNum : 3; // Slot number per frame synchronization
}i2sSlotCtrl_t;
/** \brief I2S Bclk Frame Synchronization Control */
typedef struct
{
uint32_t bclkPolarity : 1; // Bclk Polarity
uint32_t fsPolarity : 1; // Frame Synchronization Polarity
uint32_t fsWidth : 6; // Frame Synchronization width
}i2sBclkFsCtrl_t;
/** \brief I2S DMA Control */
typedef struct
{
uint32_t rxDmaReqEn : 1; // Rx Dma Req Enable
uint32_t txDmaReqEn : 1; // Tx Dma Req Enable
uint32_t rxDmaTimeOutEn : 1; // Rx Dma Timeout Enable
uint32_t dmaWorkWaitCycle : 5; // Dma Work Wait Cycle
uint32_t rxDmaBurstSizeSub1 : 4; // Rx Dma Burst Size subtract 1
uint32_t txDmaBurstSizeSub1 : 4; // Tx Dma Burst Size subtract 1
uint32_t rxDmaThreadHold : 4; // Rx Dma Threadhold
uint32_t txDmaThreadHold : 4; // Tx Dma Threadhold
uint32_t rxFifoFlush : 1; // Rx Fifo flush
uint32_t txFifoFlush : 1; // Tx Fifo flush
}i2sDmaCtrl_t;
/** \brief I2S Interrupt Control */
typedef struct
{
uint32_t txUnderRunIntEn : 1; // Tx Underrun interrupt Enable
uint32_t txDmaErrIntEn : 1; // Tx Dma Err Interrupt Enable
uint32_t txDatIntEn : 1; // Tx Data Interrupt Enable
uint32_t rxOverFlowIntEn : 1; // Rx Overflow Interrupt Enable
uint32_t rxDmaErrIntEn : 1; // Rx Dma Err Interrupt Enable
uint32_t rxDatIntEn : 1; // Rx Data Interrupt Enable
uint32_t rxTimeOutIntEn : 1; // Rx Timeout Interrupt Enable
uint32_t fsErrIntEn : 1; // Frame Start Interrupt Enable
uint32_t frameStartIntEn : 1; // Frame End Interrupt Enable
uint32_t frameEndIntEn : 1; // Frame End Interrupt Enable
uint32_t cspiBusTimeOutIntEn : 1; // Not use
uint32_t txIntThreshHold : 4; // Tx Interrupt Threadhold
uint32_t rxIntThreshHold : 4; // Rx Interrupt Threadhold
}i2sIntCtrl_t;
/** \brief I2S Timeout Cycle */
typedef struct
{
uint32_t rxTimeOutCycle : 24; // Rx Timeout cycle
}i2sTimeOutCycle_t;
/** \brief I2S Status */
typedef struct
{
uint32_t txUnderRun : 1; // Tx Underrun
uint32_t txDmaErr : 1; // Tx Dma Err
uint32_t txDataRdy : 1; // Tx Data ready, readOnly
uint32_t rxOverFlow : 1; // Rx OverFlow
uint32_t rxDmaErr : 1; // Rx Dma Err
uint32_t rxDataRdy : 1; // Rx Data ready, readOnly
uint32_t rxFifoTimeOut : 1; // Rx Fifo timeout
uint32_t fsErr : 4; // Frame synchronization Err
uint32_t frameStart : 1; // Frame start
uint32_t frameEnd : 1; // Frame end
uint32_t txFifoLevel : 6; // Tx Fifo Level, readOnly
uint32_t rxFifoLevel : 6; // Rx Fifo level, readOnly
uint32_t cspiBusTimeOut : 1; // Not use
}i2sStats_t;
/** \brief I2S Control */
typedef struct
{
uint32_t i2sMode : 2; // I2S Mode
}i2sCtrl_t;
/** \brief I2S Auto Configure Control */
typedef struct
{
uint32_t autoCgEn : 1; // Auto Configure Enable
}i2sAutoCgCtrl_t;
/**
\brief I2S control bits.
*/
#define I2S_CTRL_TRANSABORT (1UL << 0) // I2S trans abort
#define I2S_CTRL_SAMPLE_RATE_SLAVE (1UL << 1) // I2S sample rate setting, used in ec618 slave mode
#define I2S_CTRL_SAMPLE_RATE_MASTER (1UL << 2) // I2S sample rate setting, used in ec618 master mode
#define I2S_CTRL_SET_TOTAL_NUM (1UL << 3) // Audio source total num
#define I2S_CTRL_DATA_FORMAT (1UL << 4) // I2S data format
#define I2S_CTRL_SLOT_CTRL (1UL << 5) // I2S slot ctrl
#define I2S_CTRL_BCLK_FS_CTRL (1UL << 6) // I2S bclk fs ctrl
#define I2S_CTRL_DMA_CTRL (1UL << 7) // I2S dma ctrl
#define I2S_CTRL_INT_CTRL (1UL << 8) // I2S int ctrl
#define I2S_CTRL_TIMEOUT_CYCLE (1UL << 9) // I2S timeout cycle
#define I2S_CTRL_STATUS (1UL << 10) // I2S status
#define I2S_CTRL_I2SCTL (1UL << 11) // I2S control
#define I2S_CTRL_AUTO_CG_CTRL (1UL << 12) // I2S auto cg ctrl
#define I2S_CTRL_INIT (1UL << 13) // I2S init
#define I2S_CTRL_START_STOP (1UL << 14) // I2S audio play start/stop ctrl
#ifdef __cplusplus
}
#endif
#endif /* BSP_I2S_H */

View File

@@ -0,0 +1,147 @@
/****************************************************************************
*
* Copy right: 2018-, Copyrigths of AirM2M Ltd.
* File name: ic.h
* Description: EC618 interrupt controller header file
* History: Rev1.0 2018-11-15
*
****************************************************************************/
#ifndef _IC_EC618_H
#define _IC_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup xic_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#define NUM_APXIC_MODULE (4U) /**< number of XIC module */
#define NUM_APXIC0_INT (32U) /**< number of interrupts in XIC0 */
#define NUM_APXIC1_INT (32U) /**< number of interrupts in XIC1 */
#define NUM_APXIC2_INT (32U) /**< number of interrupts in XIC2 */
#define NUM_APXIC3_INT (32U) /**< number of interrupts in XIC3 */
/** ISR function type define */
typedef void ( *ISRFunc_T )(void);
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
\fn void IC_PowupInit(void)
\brief Initialize the interrupt controller, including HW configuration and ISR initialization,
called when POR or wakeup from Hibernate, in which the SRAM contents have been lost.
*/
void IC_PowupInit(void);
/**
\fn void IC_Powoff(void)
\brief DeInitialize the interrupt controller, including HW configuration and ISR initialization.
*/
void IC_Powoff(void);
/**
\fn void XIC_SetVector(IRQn_Type IRQn, ISRFunc_T vector)
\brief Sets an XIC interrupt vector in SRAM based interrupt vector table.
Use this function to bind the XIC interrupt and application ISR.
\param[in] IRQn Interrupt number
\param[in] vector Address of interrupt handler function
\note The interrupt number must be positive
*/
void XIC_SetVector(IRQn_Type IRQn, ISRFunc_T vector);
/**
\fn void XIC_EnableIRQ(IRQn_Type IRQn)
\brief Enables a device specific interrupt in the XIC interrupt controller.
\param[in] IRQn Interrupt number
\note The interrupt number must be positive
*/
void XIC_EnableIRQ(IRQn_Type IRQn);
/**
\fn void XIC_DisableIRQ(IRQn_Type IRQn)
\brief Disables a device specific interrupt in the XIC interrupt controller.
\param[in] IRQn Interrupt number
\note The interrupt number must be positive
*/
void XIC_DisableIRQ(IRQn_Type IRQn);
/**
\fn void XIC_BackupIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array)
\brief backup the interrupt mask and ovf setting before sleep
\param[out] mask_array mask0, mask1, clrovf0 to store the irq mask and ovf setting
\param[out] clrovf_array
\note
*/
void XIC_BackupIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array);
/**
\fn void XIC_RestoreIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array)
\brief restore the interrupt mask and ovf setting after sleep
\param[in] mask_array mask0, mask1, clrovf0 is the stored value before sleep
\param[out] clrovf_array
\note
*/
void XIC_RestoreIRQSetting(uint32_t *mask_array, uint32_t *clrovf_array);
/**
\fn void XIC_SetPendingIRQ(IRQn_Type IRQn)
\brief Sets the pending bit of a device specific interrupt in the XIC pending register,
mainly used for SW generating interrupt.
\param[in] IRQn Interrupt number
\note The interrupt number must be positive
*/
void XIC_SetPendingIRQ(IRQn_Type IRQn);
/**
\fn void XIC_ClearPendingIRQ(IRQn_Type IRQn)
\brief Clears the pending bit of a device specific interrupt in the XIC pending register.
\param[in] IRQn Interrupt number
\note The interrupt number must be positive
*/
void XIC_ClearPendingIRQ(IRQn_Type IRQn);
/**
\fn uint32_t XIC_LatchIRQ(XIC_TypeDef* xic)
\brief Latch the pending interrupt status to the latch register and read out.
\param[in] xic Pointer to XIC instance
\return Interrupt status
*/
uint32_t XIC_LatchIRQ(XIC_TypeDef* xic);
/**
\fn void XIC_SuppressOvfIRQ(IRQn_Type IRQn)
\brief Suppress overflow IRQ
\param[in] IRQn Interrupt number
\note The interrupt number must be positive
*/
void XIC_SuppressOvfIRQ(IRQn_Type IRQn);
/**
\fn void XIC_ClearAllPendingIRQ(XIC_TypeDef* xic)
\brief Clears all pending bits of a XIC interrupt controller.
\param[in] xic Pointer to XIC instance
*/
void XIC_ClearAllPendingIRQ(XIC_TypeDef* xic);
/** \} */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,233 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: kpc_ec618.h
* Description: EC618 kpc driver header file
* History: Rev1.0 2021-07-23
*
****************************************************************************/
#ifndef _KPC_EC618_H
#define _KPC_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup kpc_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief List of debounce clock divider ratio */
typedef enum
{
KPC_DEBOUNCE_CLK_DIV_RATIO_2 = 1U, /**< KPC debounce clock divider ratio select as 2 */
KPC_DEBOUNCE_CLK_DIV_RATIO_4 = 2U, /**< KPC debounce clock divider ratio select as 4 */
KPC_DEBOUNCE_CLK_DIV_RATIO_8 = 3U, /**< KPC debounce clock divider ratio select as 8 */
KPC_DEBOUNCE_CLK_DIV_RATIO_16 = 4U, /**< KPC debounce clock divider ratio select as 16 */
KPC_DEBOUNCE_CLK_DIV_RATIO_32 = 5U, /**< KPC debounce clock divider ratio select as 32 */
KPC_DEBOUNCE_CLK_DIV_RATIO_64 = 6U, /**< KPC debounce clock divider ratio select as 64 */
KPC_DEBOUNCE_CLK_DIV_RATIO_128 = 7U, /**< KPC debounce clock divider ratio select as 128 */
KPC_DEBOUNCE_CLK_DIV_RATIO_256 = 8U, /**< KPC debounce clock divider ratio select as 256 */
KPC_DEBOUNCE_CLK_DIV_RATIO_512 = 9U, /**< KPC debounce clock divider ratio select as 512 */
KPC_DEBOUNCE_CLK_DIV_RATIO_1024 = 10U, /**< KPC debounce clock divider ratio select as 1024 */
KPC_DEBOUNCE_CLK_DIV_RATIO_2048 = 11U, /**< KPC debounce clock divider ratio select as 2048 */
KPC_DEBOUNCE_CLK_DIV_RATIO_4096 = 12U, /**< KPC debounce clock divider ratio select as 4096 */
KPC_DEBOUNCE_CLK_DIV_RATIO_8192 = 13U, /**< KPC debounce clock divider ratio select as 8192 */
KPC_DEBOUNCE_CLK_DIV_RATIO_16384 = 14U, /**< KPC debounce clock divider ratio select as 16384 */
KPC_DEBOUNCE_CLK_DIV_RATIO_32768 = 15U, /**< KPC debounce clock divider ratio select as 32768 */
} KpcDebounceClkDivRatio_t;
/** \brief List of debounce width */
typedef enum
{
KPC_DEBOUNCE_WIDTH_5_CYCLES = 5U, /**< KPC debounce width is 5 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_6_CYCLES = 6U, /**< KPC debounce width is 6 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_7_CYCLES = 7U, /**< KPC debounce width is 7 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_8_CYCLES = 8U, /**< KPC debounce width is 8 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_9_CYCLES = 9U, /**< KPC debounce width is 9 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_10_CYCLES = 10U, /**< KPC debounce width is 10 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_11_CYCLES = 11U, /**< KPC debounce width is 11 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_12_CYCLES = 12U, /**< KPC debounce width is 12 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_13_CYCLES = 13U, /**< KPC debounce width is 13 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_14_CYCLES = 14U, /**< KPC debounce width is 14 Cycles of debounce clock */
KPC_DEBOUNCE_WIDTH_15_CYCLES = 15U, /**< KPC debounce width is 15 Cycles of debounce clock */
} KpcDebounceWidth_t;
/** \brief List of key scan polarity */
typedef enum
{
KPC_SCAN_POLARITY_0 = 0U, /**< KPC outputs low level scan waveform for active row while other valid rows is high */
KPC_SCAN_POLARITY_1 = 1U, /**< KPC outputs high level scan waveform for active row while other valid rows is low */
} KpcScanPolarity_t;
/** \brief List of key scan divider ratio */
typedef enum
{
KPC_SCAN_DIV_RATIO_2 = 1U, /**< KPC scan frequence divider ratio set as 2 */
KPC_SCAN_DIV_RATIO_4 = 2U, /**< KPC scan frequence divider ratio set as 4 */
KPC_SCAN_DIV_RATIO_8 = 3U, /**< KPC scan frequence divider ratio set as 8 */
KPC_SCAN_DIV_RATIO_16 = 4U, /**< KPC scan frequence divider ratio set as 16 */
KPC_SCAN_DIV_RATIO_32 = 5U, /**< KPC scan frequence divider ratio set as 32 */
KPC_SCAN_DIV_RATIO_64 = 6U, /**< KPC scan frequence divider ratio set as 64 */
KPC_SCAN_DIV_RATIO_128 = 7U, /**< KPC scan frequence divider ratio set as 128 */
} KpcScanDivRatio_t;
/** \brief List of debounce width */
typedef enum
{
KPC_ROW_0 = 1U, /**< KPC row0 enable mask */
KPC_ROW_1 = 2U, /**< KPC row1 enable mask */
KPC_ROW_2 = 4U, /**< KPC row2 enable mask */
KPC_ROW_3 = 8U, /**< KPC row3 enable mask */
KPC_ROW_4 = 16U, /**< KPC row4 enable mask */
KPC_ROW_ALL = 0x1FU /**< KPC all rows enable mask */
} KpcRow_t;
/** \brief List of debounce width */
typedef enum
{
KPC_COLUMN_0 = 1U, /**< KPC column0 enable mask */
KPC_COLUMN_1 = 2U, /**< KPC column1 enable mask */
KPC_COLUMN_2 = 4U, /**< KPC column2 enable mask */
KPC_COLUMN_3 = 8U, /**< KPC column3 enable mask */
KPC_COLUMN_4 = 16U, /**< KPC column4 enable mask */
KPC_COLUMN_ALL = 0x1FU /**< KPC all columns enable mask */
} KpcColumn_t;
/** \brief KPC debounce configuration, decounce exits when consecutive debounceWidth scans give the same result */
typedef struct
{
KpcDebounceClkDivRatio_t debounceClkDivRatio; /**< debounce clock divider ratio */
KpcDebounceWidth_t debounceWidth; /**< debounce width */
} KpcDebounceConfig_t;
/** \brief KPC auto repeat configuration */
typedef struct
{
uint8_t enable; /**< enable auto repeat or not */
uint8_t delay; /**< auto repeat delay cycles of scan period, if scan period is 50ms and this value is set as 10,
then autorepeat event will start to be reported 500ms later after key press is detected and key press keeps hold */
uint8_t period; /**< auto repeat report interval of scan period, if scan period is 50ms and this value is set as 2,
then autorepeat event will be reported in interval of 100ms until key is released */
} KpcAutoRepeatConfig_t;
/** \brief KPC configuration structure */
typedef struct
{
uint8_t validRowMask; /**< Bitmap of valid rows */
uint8_t validColumnMask; /**< Bitmap of valid columns */
KpcDebounceConfig_t debounceConfig; /**< KPC debounce configuration */
KpcAutoRepeatConfig_t autoRepeat; /**< KPC auto repeat configuration */
KpcScanPolarity_t scanPolarity; /**< KPC scan polarity */
KpcScanDivRatio_t scanDivRatio; /**< KPC scan divider ratio */
} KpcConfig_t;
/** \brief List of kpc report key value */
typedef enum
{
KPC_REPORT_KEY_RELEASE = 0U, /**< Key is released */
KPC_REPORT_KEY_PRESS = 1U, /**< Key is pressed */
KPC_REPORT_KEY_REPEAT = 2U, /**< Key holds pressed */
} KpcReportValue_t;
typedef struct
{
uint8_t value : 2; /**< Key value */
uint8_t column : 3; /**< Key column */
uint8_t row : 3; /**< Key row */
} KpcReportEvent_t;
/**
\brief Defines callback function prototype.
Callback function will be called in KPC interrupt service routine
\param report key event value
*/
typedef void (*kpc_callback_t)(KpcReportEvent_t event);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name KPC Configuration */
/** \{ */
/**
\fn void KPC_getDefaultConfig(KpcConfig_t *config)
\brief Gets the KPC default configuartion.
This function sets the configuration structure to default values as below:
\code
config->debounceConfig.debounceClkDivRatio = KPC_DEBOUNCE_CLK_DIV_RATIO_16384;
config->debounceConfig.debounceWidth = KPC_DEBOUNCE_WIDTH_7_CYCLES;
config->validRowMask = KPC_ROW_ALL;
config->validColumnMask = KPC_COLUMN_ALL;
config->scanPolarity = KPC_SCAN_POLARITY_0;
config->scanDivRatio = KPC_SCAN_DIV_RATIO_16;
config->autoRepeat.enable = 1;
config->autoRepeat.delay = 10;
config->autoRepeat.period = 1;
\endcode
\details debouncer and scan setting explaination:
KPC input clock is 26M, if debouncer divider is set as KPC_DEBOUNCE_CLK_DIV_RATIO_16384, then one cycle is 16384/26M = 630us,
debouncer depth set as 7, means we can filter out 630*7us(4.4ms) jitter
scan clock is sourced from debouncer clock, which means if scan frequency divider ratio is set as KPC_SCAN_DIV_RATIO_16 and
when 5 rows are enabled, the scan frequency is 26M/16384/16/5 = 20HZ, each row scan signal width will be 1/20/5 = 10ms
\param[in] config Pointer to KPC configuration structure
*/
void KPC_getDefaultConfig(KpcConfig_t *config);
/**
\fn void KPC_init(const KpcConfig_t *config, kpc_callback_t callback)
\brief Initialize KPC
\param[in] config Pointer to KPC configuration
\param[in] callback Function to be called when KPC interrupt occurs
\return ARM_DRIVER_OK if the setting is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
*/
int32_t KPC_init(const KpcConfig_t *config, kpc_callback_t callback);
/**
\fn void KPC_deInit(void)
\brief Deinitialize KPC
*/
void KPC_deInit(void);
/**
\fn void KPC_startScan(void)
\brief Starts KPC scan
*/
void KPC_startScan(void);
/**
\fn void KPC_stopScan(void)
\brief Stops KPC scan
*/
void KPC_stopScan(void);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _KPC_EC618_H */

View File

@@ -0,0 +1,143 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: oneWire.h
* Description: EC618 one wire bus driver file
* History: Rev1.0 2020-12-17
*
****************************************************************************/
#ifndef _ONEWIRE_EC618_H
#define _ONEWIRE_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup onewire_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief OW Mode Select */
typedef enum
{
STANDARD = 0, /**< Stand speed of onewire */
OVERDRIVE /**< High speed of onewire */
}OwModeSel_e;
/** \brief OW Status */
typedef enum
{
OW_IDLE = 0x0,
OW_RESET_SUCCESS = 0x2,
OW_RESETPD_SUCCESS = 0x4,
OW_READ_SUCCESS = 0x8,
OW_WRITE_SUCCESS = 0x10,
OW_TIMEOUT = 0x20,
}OwStats_e;
typedef struct
{
uint8_t *dataWrite;
uint8_t *dataRead;
uint8_t mode;
}OwRes_t;
#define OWDRV_OK (0)
#define OWDRV_RESET_ERR (-1)
#define OWDRV_RESETPD_ERR (-2)
#define OWDRV_READ_ERR (-3)
#define OWDRV_WRITE_ERR (-4)
#define OWDRV_TIMEOUT (-5)
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
\fn void owInit()
\brief Initialize ow
*/
void owInit(void);
/**
\fn void owDeInit()
\brief DeInitialize ow
*/
void owDeInit(void);
/**
\fn void owSetMode(OwModeSel_e mode)
\brief ow set mode
\param[in] mode ow mode
*/
void owSetMode(OwModeSel_e mode);
/**
\fn int32_t owReset()
\brief ow reset
\return ow reset status
*/
int32_t owReset(void);
/**
\fn int32_t owResetPd()
\brief ow reset for presence detect
\return ow reset presence detect status
*/
int32_t owResetPd(void);
/**
\fn int32_t owWriteBit(uint8_t data)
\brief write 1bit data to ow
\param[in] data data to write to ow, LSB is effective
\return ow write 1 bit status
*/
int32_t owWriteBit(uint8_t data);
/**
\fn int32_t owWriteByte(uint8_t data)
\brief write 1byte data to ow
\param[in] data 1 byte data to write to ow
\return ow write 1 byte status
*/
int32_t owWriteByte(uint8_t data);
/**
\fn int32_t owReadBit()
\brief read 1bit data
\return ow read 1 bit status
*/
int32_t owReadBit(uint8_t * dataRead);
/**
\fn int32_t owReadByte()
\brief ow read 1 byte
\return ow read 1 byte status
*/
int32_t owReadByte(uint8_t * dataRead);
/**
\fn int32_t owTouchByte(uint8_t data)
\brief read and write ow at the same time
\return ow touch 1 byte status
*/
int32_t owTouchByte(uint8_t data);
/** \} */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,173 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: pad.h
* Description: EC618 pad driver header file
* History:
*
****************************************************************************/
#ifndef _PAD_EC618_H_
#define _PAD_EC618_H_
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup pad_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief PAD pin mux selection */
typedef enum
{
PAD_MUX_ALT0 = 0U, /**< Chip-specific */
PAD_MUX_ALT1 = 1U, /**< Chip-specific */
PAD_MUX_ALT2 = 2U, /**< Chip-specific */
PAD_MUX_ALT3 = 3U, /**< Chip-specific */
PAD_MUX_ALT4 = 4U, /**< Chip-specific */
PAD_MUX_ALT5 = 5U, /**< Chip-specific */
PAD_MUX_ALT6 = 6U, /**< Chip-specific */
PAD_MUX_ALT7 = 7U, /**< Chip-specific */
} PadMux_e;
/** \brief Internal pull-up resistor configuration */
typedef enum
{
PAD_PULL_UP_DISABLE = 0U, /**< Internal pull-up resistor is disabled */
PAD_PULL_UP_ENABLE = 1U, /**< Internal pull-up resistor is enabled */
} PadPullUp_e;
/** \brief Internal pull-down resistor configuration */
typedef enum
{
PAD_PULL_DOWN_DISABLE = 0U, /**< Internal pull-down resistor is disabled */
PAD_PULL_DOWN_ENABLE = 1U, /**< Internal pull-down resistor is enabled */
} PadPullDown_e;
/** \brief Pull feature selection */
typedef enum
{
PAD_PULL_AUTO = 0U, /**< Pull up/down is controlled by muxed alt function */
PAD_PULL_INTERNAL = 1U, /**< Use internal pull-up/down resistor */
} PadPullSel_e;
/** \brief Input buffer enable/disable */
typedef enum
{
PAD_INPUT_BUFFER_DISABLE = 0U, /**< Input Buffer is disabled */
PAD_INPUT_BUFFER_ENABLE = 1U, /**< Input Buffer is enabled */
} PadInputBuffer_e;
/** \brief Configures pull feature */
typedef enum
{
PAD_INTERNAL_PULL_UP = 0U, /**< select internal pull up */
PAD_INTERNAL_PULL_DOWN = 1U, /**< select internal pull down */
PAD_AUTO_PULL = 2U, /**< Pull up/down is controlled by muxed alt function */
} PadPullConfig_e;
/** \brief PAD configuration structure */
typedef struct
{
uint32_t : 4;
uint32_t mux : 3; /**< Pad mux configuration */
uint32_t : 1;
uint32_t pullUpEnable : 1; /**< Enable pull-up */
uint32_t pullDownEnable : 1; /**< Enable pull-down */
uint32_t pullSelect : 1; /**< Pull select, external or internal control */
uint32_t : 2;
uint32_t inputBufferEnable : 1; /**< Enable/disable input buffer */
uint32_t : 18;
} PadConfig_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name PAD Driver Initialization */
/** \{ */
/**
\fn void PAD_driverInit(void);
\brief Intialize PAD driver internal data, must be called before any other APIs
*/
void PAD_driverInit(void);
/**
\fn void PAD_driverInit(void);
\brief De-Intialize PAD driver, disable PAD clock and perform some clearups
*/
void PAD_driverDeInit(void);
/** \} */
/** \name Configuration */
/* \{ */
/**
\fn void PAD_getDefaultConfig(PadConfig_t *config)
\brief Gets the PAD default configuartion
This function sets the configuration structure to default values as below:
\code
config->mux = PAD_MUX_ALT0;
config->inputBufferEnable = PAD_INPUT_BUFFER_DISABLE;
config->pullSelect = PAD_PULL_AUTO;
config->pullUpEnable = PAD_PULL_UP_DISABLE;
config->pullDownEnable = PAD_PULL_DOWN_DISABLE;
\endcode
\param config Pointer to PAD configuration structure
*/
void PAD_getDefaultConfig(PadConfig_t *config);
/**
\fn void PAD_setPinConfig(uint32_t pin, const PadConfig_t *config)
\brief Sets the pad PCR register
\param pin PAD pin number
\param config Pointer to PAD configuration structure
*/
void PAD_setPinConfig(uint32_t paddr, const PadConfig_t *config);
/**
\fn void PAD_setPinMux(uint32_t pin, PadMux_e mux)
\brief Configures pin mux
\param pin PAD pin number
\param mux pin signal source selection
*/
void PAD_setPinMux(uint32_t paddr, PadMux_e mux);
/**
\fn void PAD_enablePinInputBuffer(uint32_t pin, bool enable)
\brief Enable/disable pin's input buffer
\param pin PAD pin number
\param enable true to enable, false to disable
*/
void PAD_enablePinInputBuffer(uint32_t paddr, bool enable);
/**
\fn void PAD_setPinPullConfig(uint32_t pin, PadPullConfig_e config)
\brief Configures pin's pull feature
\param pin PAD pin number
\param config PAD pin pull configuration
*/
void PAD_setPinPullConfig(uint32_t paddr, PadPullConfig_e config);
/** \} */
/** \}*/
#if defined(__cplusplus)
}
#endif
#endif /* _PAD_EC618_H_ */

View File

@@ -0,0 +1,167 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename: pwrkey.h
*
* Description: header of pwrkey.c, power on/off and software debounce
*
* History: 2021.04.29 initiated by Zhao Weiqi
*
* Notes:
*
******************************************************************************/
#ifndef PWR_KEY_H
#define PWR_KEY_H
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
#define KEY_BUF_SIZE 8
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
typedef struct
{
int16_t longPressTimeout;
int16_t repeatTimeout;
int16_t pwrOffTimeout;
}pwrKeyDly_t;
typedef enum
{
PWRKEY_PWRON_MODE = 0,
PWRKEY_WAKEUP_LOWACTIVE_MODE,
PWRKEY_WAKEUP_HIGHACTIVE_MODE,
PWRKEY_UNKNOW_MODE,
}pwrKeyWorkMode;
/*
typedef enum
{
PWRKEY_SYSTEM_ON = 0,
PWRKEY_SYSTEM_OFF,
}pwrKeySysStatus;
*/
typedef enum
{
PWRKEY_RELEASE = 0,
PWRKEY_PRESS,
PWRKEY_LONGPRESS,
PWRKEY_REPEAT,
}pwrKeyPressStatus;
typedef struct
{
bool negEdgeEn;
bool posEdgeEn;
}pwrKeyWakeupCfg_t;
typedef void(* pwrKeyCallback_t)(pwrKeyPressStatus status);
typedef struct
{
pwrKeyWorkMode workMode;
pwrKeyWakeupCfg_t wakeupCfg;
pwrKeyDly_t delayCfg;
pwrKeyCallback_t pwrKeyCallback;
pwrKeyPressStatus curStatus;
pwrKeyPressStatus keyBuf[KEY_BUF_SIZE];
uint8_t bufOffset;
}pwrKeyInfo_t;
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
/**
* @brief pwrKeyPushKey
* @details push a key to power key buffer
*
* @param pwrKeyInfo
@param status
* @return null
*/
void pwrKeyPushKey(pwrKeyInfo_t *pwrKeyInfo, pwrKeyPressStatus status);
/**
* @brief pwrKeyPopKey
* @details pop a key from power key buffer and return the key status
*
* @param pwrKeyInfo
* @return null
*/
pwrKeyPressStatus pwrKeyPopKey(pwrKeyInfo_t *pwrKeyInfo);
/**
* @brief pwrKeyStartPowerOff
* @details force to enter power off status
*
* @return null
*/
void pwrKeyStartPowerOff(void);
/**
* @brief pwrkeyPwrOnDebounce
* @details power on debounce flow according to the configures
*
* @param tmpDelay in ms
* @return null
*/
void pwrkeyPwrOnDebounce(int16_t tmpDelay);
/**
* @brief pwrKeyHwInit
* @details power key hardware init
*
* @param pullUpEn
* @return null
*/
void pwrKeyHwInit(bool pullUpEn);
/**
* @brief pwrKeyHwDeinit
* @details power key hardware deinit
*
* @param pullUpEn
* @return null
*/
void pwrKeyHwDeinit(bool pullUpEn);
/**
* @brief pwrKeyGetPinLevel
* @details get power key pin value
*
* @return null
*/
bool pwrKeyGetPinLevel(void);
/**
* @brief pwrKeyGetPwrKeyMode
* @details get power key mode in bootloader
*
* @return null
*/
pwrKeyWorkMode pwrKeyGetPwrKeyMode(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,87 @@
#ifndef __RNG_EC618_H__
#define __RNG_EC618_H__
#include "ec618.h"
#include "Driver_Common.h"
#include "clock.h"
#include "ic.h"
#include "string.h"
#define RNG_DEBUG_USING_PRINTF 0
#define RNG_DEBUG_USING_UNILOG 0
#define RNG_IRQ_MODE 0
#define RNG_MAX_POLL_DELAY_US (8000*2)
#define RNG_MAX_TRY_NUM 10
#define RNG ((RngDesc_t*)MP_TRNG_BASE_ADDR)
#define RNG_R_MAGIC 0xf45a97d4
#if (RNG_DEBUG_USING_UNILOG == 1)
#include DEBUG_LOG_HEADER_FILE
#endif
#ifdef PM_FEATURE_ENABLE
#include "slpman.h"
#endif
#if RNG_DEBUG_USING_PRINTF
#define RNGDEBUG(...) printf(__VA_ARGS__)
#else
#define RNGDEBUG(...)
#endif
typedef struct
{
__IM uint32_t rsvd1[64];
__IO uint32_t imrReg; //Interrupt mask reg ,0x100
__IO uint32_t isrReg; //Interrupt status reg
__OM uint32_t icrReg; //Interrupt clear reg
__IO uint32_t cfgReg; //Configuration reg
__IM uint32_t validReg; //Valid reg
__IM uint32_t dataReg[6];
__IO uint32_t srcEnableReg; //Random source enable reg
__IO uint32_t sampleCntReg; //Sample Count reg
__IO uint32_t autoCorrReg; //Auto correlation reg
__IM uint32_t debugCtrlReg; //Debug Control reg
__IM uint32_t rsvd2;
__OM uint32_t swRstReg; //Reset reg
__IM uint32_t rsvd3[29];
__IM uint32_t busyReg; //Busy reg
__OM uint32_t rstBitsCntReg; //Reset bits counter reg
__IM uint32_t rsvd4[8];
__IM uint32_t bistCntReg[3]; //BIST Counter reg
__IO uint32_t rsvd5[5];
}RngDesc_t;
typedef enum
{
RNG_SRC_SHORT_TEST_TYPE = 0,
RNG_SRC_SHORT_TYPE = 1,
RNG_SRC_LONG_TYPE = 2,
RNG_SRC_LONGEST_TYPE = 3,
}RngSrcSelType_e;
#define RNGDRV_OK (0)
#define RNGDRV_IntErr (-1)
#define RNGDRV_TimeOutErr (-2)
typedef enum{
RNG_EHR_VALID_TYPE = 1,
RNG_AUTO_CORR_ERR_TYPE = 2,
RNG_CRNGT_ERR_TYPE = 4,
RNG_VN_ERR_TYPE = 8
}RngIntStatType_e;
/**
\brief When rand is null, means generate random number to efuse. If rand isn't null, means generate to this parameter.
\param[out] rand Memory address to receive generated random number.
\return status
*/
int32_t rngGenRandom(uint8_t rand[24]);
#endif

View File

@@ -0,0 +1,543 @@
#ifndef __SCT_REG_H__
#define __SCT_REG_H__
/******************************************************************************
******************************************************************************
Copy right: 2017-, Copyrigths of AirM2M Ltd.
File name: sctreg.h
Description: SCT register, Security Top is a HW use to do:
* 1) cipher & integrity check
* 2) AES/SHA
* 3) PPP escape & CRC
* 4) USB TX
History: 2020/12/04 Originated by Jason
******************************************************************************
******************************************************************************/
#include "ec618.h"
#if defined(__CC_ARM)
#pragma anon_unions
#endif
/******************************************************************************
******************************************************************************
* SCT control registers
******************************************************************************
******************************************************************************/
/*
* Cipher 0x4005-0000~0x4005-FFFF (64KB)
*/
#define SCT_REG_ADDR 0x40050000
/******************************************************************************
* SCT enable/disable register
******************************************************************************/
#define SCT_EN_CTRL_REG ((__IO UINT32 *)SCT_REG_ADDR)
/*
* __IO UINT32 SCTEN;
* Bit WIDTH DESP
* 0 1 0 - SCT disable (reset value)
* 1- SCT enable
* 1:31 31 RSVD
*/
#define ENABLE_SCT() ((*(SCT_EN_CTRL_REG)) = 1)
#define DISABLE_SCT() ((*(SCT_EN_CTRL_REG)) = 0)
/******************************************************************************
******************************************************************************
* SCT RNDIS/PPP config register
******************************************************************************
******************************************************************************/
/*
* SctRndisCrcCfgReg RNDIS_CRC_CFG
* Bit WIDTH DESP
* 0 1 rndis_crc_in_bit_swap,
* 0 - CRC calc from bit: inByte[0]
* 1 - CRC calc from bit: inByte[7] (reset value)
* 1 1 rndis_crc_comple_out
* 0 - CRC out bit not comple
* 1 - CRC out bit comple (reset value)
* 2 1 rndis_crc_out_bit_swap
* 0 - CRC out bit not swap
* 1 - CRC out bit swap (reset value)
* 3:6 4 rndis_crc_comple_in_num, how many input bytes need to be compled
*
*/
typedef union
{
struct {
UINT32 crcInBitSwap : 1;
UINT32 crcCompleOut : 1;
UINT32 crcOutBitSwap : 1;
UINT32 crcCompleInNum : 4;
UINT32 : 25;
};
UINT32 value32;
}SctRndisCrcCfgReg;
/*
* SctPPPCrcInitReg PPP_CRC_INIT
* Bit WIDTH DESP
* 0:15 16 PPP CRC init value, reset value: 0xFFFF
*/
typedef union
{
struct {
UINT32 crcInitValue : 16;
UINT32 : 16;
};
UINT32 value32;
}SctPPPCrcInitReg;
/*
* SctPPPCrcCfgReg PPP_CRC_CFG
* Bit WIDTH DESP
* 0 1 ppp_crc_in_bit_swap
* 0 - CRC calc from bit: inByte[0], (reset value)
* 1 - CRC calc from bit: inByte[7]
* 1 1 ppp_crc_comple_out
* 0 - CRC out bit not comple
* 1 - CRC out bit comple, (reset value)
* 2 1 ppp_crc_out_bit_swap
* 0 - CRC out bit not swap
* 1 - CRC out bit swap (reset value)
*
*/
typedef union
{
struct {
UINT32 crcInBitSwap : 1;
UINT32 crcCompleOut : 1;
UINT32 crcOutBitSwap : 1;
UINT32 : 29;
};
UINT32 value32;
}SctPPPCrcCfgReg;
/*
* PPP escape/deescape bitmap table
*/
#define SCT_PPP_ESCP_BITMAP_WORD_NUM 8
#define SCT_PPP_DE_ESCP_BITMAP_WORD_NUM 8
/*
* SCT RNDIS PPP config register struct
*/
typedef struct SctRndisPPPCfgReg_Tag
{
__IO UINT32 RNDIS_CRC_INIT; /* RNDIS (802.3) CRC init value, reset value: 0, offset: 0x04 */
__IO SctRndisCrcCfgReg RNDIS_CRC_CFG; /* RNDIS (802.3) CRC config. offset: 0x08 */
__IO SctPPPCrcInitReg PPP_CRC_INIT; /* PPP CRC init value, reset value: 0xFFFF, offset: 0x0C */
__IO SctPPPCrcCfgReg PPP_CRC_CFG; /* PPP CRC config, offset: 0x10 */
__IO UINT32 PPP_ESCP_BITMAP[SCT_PPP_ESCP_BITMAP_WORD_NUM]; /* PPP escape bitmap, offset: 0x14 */
__IO UINT32 PPP_DE_ESCP_BITMAP[SCT_PPP_DE_ESCP_BITMAP_WORD_NUM];/* PPP de-escape bitmap, offset: 0x34 */
}SctRndisPPPCfgReg;
/*
* SCT RNDIS PPP config register start address
*/
#define SCT_RNDIS_PPP_CTRL_REG_ADDR (SCT_REG_ADDR + 0x04)
/*
* SCT RNDIS PPP register pointer
*/
#define SCT_RNDIS_PPP_CFG_REG ((SctRndisPPPCfgReg *)SCT_RNDIS_PPP_CTRL_REG_ADDR)
/******************************************************************************
******************************************************************************
* SCT (cipher/integrity) common config register
******************************************************************************
******************************************************************************/
/*
* SctCommCfgWord0 COMM_CFG0
* Bit WIDTH DESP
* 0 1 sct_cfg_acg_en_rmi_acg
* 0 - not enable auto gate, (reset value)
* 1 - enable auto gate
* 1 1 sct_cfg_acg_en_ahb_acg
* 0 - not enable auto gate, (reset value)
* 1 - enable auto gate
* 16 1 sct_cfg_unilog_SCT_ChainStart
* 0 - no unilog output, (reset value)
* 1 - unilog output
* 17 1 sct_cfg_unilog_SCT_Descriptor_done
* 0 - no unilog output, (reset value)
* 1 - unilog output
* 18 1 sct_cfg_unilog_SCT_ChainEnd
* 0 - no unilog output, (reset value)
* 1 - unilog output
* 19 1 sct_cfg_unilog_error_int
* 0 - no unilog output, (reset value)
* 1 - unilog output
* 20 1 sct_usb_lb_ind, USB Tx big/Little endian output
* 0 - little endian, (reset value)
* 1 - big endian
* 24:31 8 sct_cfg_high_addr_offst
*
*/
typedef union
{
struct {
UINT32 rmiAcg : 1;
UINT32 ahbAcg : 1;
UINT32 : 14;
UINT32 chainStartUnilog : 1;
UINT32 descDoneUnilog : 1;
UINT32 chainEndUnilog : 1;
UINT32 errorIntUnilog : 1;
UINT32 usbLBEndianInd : 1;
UINT32 : 3;
UINT32 memHighAddrOffset : 8;
};
UINT32 value32;
}SctCommCfgWord0;
/*
* SctCommCfgWord1 COMM_CFG1
* Bit WIDTH DESP
* 0:19 20 sct_cfg_d_max_time, (reset value: 0)
* descriptor max process time, in unit of 32K ticks, if timeout, tigger interrupt: sct_dscrpt_time_out
*
*/
typedef union
{
struct {
UINT32 descMaxProcTickTime : 20;
UINT32 : 12;
};
UINT32 value32;
}SctCommCfgWord1;
/*
* SCT common config register struct
*/
typedef struct SctCommCfgReg_Tag
{
__IO SctCommCfgWord0 COMM_CFG0; /* SCT common CFG0, offset: 0x54 */
__IO SctCommCfgWord1 COMM_CFG1; /* SCT common CFG1, offset: 0x58 */
}SctCommCfgReg;
/*
* SCT common control register start address
*/
#define SCT_COMM_CFG_REG_ADDR (SCT_REG_ADDR + 0x54)
/*
* SCT RNDIS PPP register pointer
*/
#define SCT_COMM_CFG_REG ((SctCommCfgReg *)SCT_COMM_CFG_REG_ADDR)
/******************************************************************************
******************************************************************************
* SCT (cipher/integrity) channel config register
******************************************************************************
******************************************************************************/
/*
*
* Bit WIDTH DESP
* 0:7 8 sct_fifo_len_ch0
* Chain FIFO length, MAX set to 255, (reset value: 0)
* 8 1 sct_chain_int_en_ch0, (reset value: 0)
* Generate interrupt when each chain in this channel is finished
* 9 1 sct_fifo_empty_int_en_ch0, (reset value: 0)
* FIFO empty interrupt enable, Generate interrupt when chain FIFO is empty (all done)
* 10 1 sct_fifo_full_int_en_ch0, (reset value: 0)
* FIFI full interrupt enable, Generate interrupt when chain FIFO is full (>sct_fifo_len_ch0)
* 11 1 sct_ck_bl_ch0, input CK is big/little endian
* 0 - little endian, (reset value: 0)
* 1 - big endian
* 12 1 sct_aes_iv_bl_ch0, input AES IV is big/little endian
* 0 - little endian, (reset value: 0)
* 1 - big endian
* 13 1 sct_ck_opt_dis_ch0, whether disable CK optimization, whether need to re-load CK from SRAM, when process descriptors in the same chain
* 0 - enable CK opt, (reset value: 0)
* 1 - disable CK opt
* 16:17 1 comm_crc_poly_len_ch0, common CRC poly length
* 0 <20>C 8 bits CRC, (reset value: 0)
* 1 <20>C 16 bits CRC
* 2 <20>C 24 bits CRC
* 3 <20>C 32 bits CRC
* 19 1 comm_crc_comple_out_ch0
* 0 - CRC output not need to comple, (reset value: 0)
* 1 - CRC output need to comple
* 20:23 4 comm_crc_comple_in_num_ch0, how many input bytes need to comple, before start CRC,
* 24 1 comm_crc_out_bit_swap_ch0
* 0 <20>C crcbyte from s[x] to s[x+7], s[x+7] is placed in LSB, (reset value: 0)
* 1 <20>C crcbyte from s[x+7] to s[x], s[x+7] is placed in MSB
* 25 1 comm_crc_in_bit_swap_ch0
* 0 <20>C CRC start from bit[0] of input byte, (reset value: 0)
* 1 <20>C CRC start from bit[7] of input byte
*
*/
typedef union
{
struct {
UINT32 fifoLen : 8;
UINT32 chainIntEn : 1;
UINT32 chainEmptyIntEn : 1;
UINT32 chainFullIntEn : 1;
UINT32 ckBLEndian : 1;
UINT32 aesIvBLEndian : 1; /* bit: 12 */
UINT32 ckOptDis : 1; /* bit: 13 */
UINT32 : 2;
UINT32 crcPolyLen : 2; /* bit: 16:17 */
UINT32 : 1;
UINT32 crcOutComple : 1; /* bit: 19 */
UINT32 crcInCompleByteNum : 4; /* bit: 20:23 */
UINT32 crcOutBitSwap : 1; /* bit: 24 */
UINT32 crcInBitSwap : 1; /* bit: 25 */
UINT32 : 6;
};
UINT32 value32;
}SctChCfgWord0;
/*
* UINT32 CHA_BASE_ADDR
* Chain Base Address. Chain FIFO start address, should be 4 bytes aligned, and with length: 4*CHAINFIFOLEN
*/
/*
* UINT32 CK_BASE_ADDR, EEA/EIA CK Base Address
* 1. Should be 4 bytes aligned
* 2. one CK/IK 16 bytes
* 3. Total 8 CK/IK keys, so total byte length: 8*16 = 128
*/
/*
* SctChCtrlReg CH_CTRL //write only
* Bit WIDTH DESP
* 0 1 sct_chain_trigger_ch0
* Set 1, Chain trigger, a chain already insert into the chain list, and trigger SCT to process
* 1 1 sct_channel_reset_ch0
* Set 1, to reset current channel
*
*/
typedef union
{
struct {
UINT32 chainTrg : 1;
UINT32 chnReset : 1;
UINT32 : 30;
};
UINT32 value32;
}SctChCtrlReg;
/*
* SCT channel config register struct
*/
typedef struct SctChannelCfgReg_Tag
{
__IO SctChCfgWord0 CH_CFG0; /* SCT channel CFG0, offset: 0x5C */
__IO UINT32 CHA_BASE_ADDR; /* SCT channel chain base address, offset: 0x60 */
__IO UINT32 CK_BASE_ADDR; /* SCT channel CK/IK base address, offset: 0x64 */
__IO UINT32 CRC_POLY; /* SCT channel common CRC poly, offset: 0x68 */
__IO UINT32 CRC_INIT; /* SCT channel common CRC init value, offset: 0x6C */
__O SctChCtrlReg CH_CTRL; /* SCT channel control register, write only, offset: 0x70 */
}SctChannelCfgReg;
/*
* SCT totoal channel number: 6
*/
#define SCT_CHANNEL_NUM 6
/*
* SCT channels config register struct
*/
typedef struct SctCHSCfgReg_Tag
{
SctChannelCfgReg chCfg[SCT_CHANNEL_NUM];
}SctCHSCfgReg;
/*
* SCT channels config register start address
*/
#define SCT_CHANNEL_CFG_REG_ADDR (SCT_REG_ADDR + 0x5C)
/*
* SCT channels config register pointer
*/
#define SCT_CHANNELS_CFG_REG ((SctCHSCfgReg *)SCT_CHANNEL_CFG_REG_ADDR)
/******************************************************************************
******************************************************************************
* SCT memory guard register
******************************************************************************
******************************************************************************/
typedef struct
{
__IO UINT32 hAddr0; /*sct_mpr_addr_h0, offset: 0xEC */
__IO UINT32 lAddr0; /*sct_mpr_addr_l0, offset: 0xF0 */
__IO UINT32 hAddr1; /*sct_mpr_addr_h1, offset: 0xF4 */
__IO UINT32 lAddr1; /*sct_mpr_addr_l1, offset: 0xF8 */
__IO UINT32 hAddr2; /*sct_mpr_addr_h2, offset: 0xFC */
__IO UINT32 lAddr2; /*sct_mpr_addr_l2, offset: 0x100 */
__IO UINT32 hAddr3; /*sct_mpr_addr_h3, offset: 0x104 */
__IO UINT32 lAddr3; /*sct_mpr_addr_l3, offset: 0x108 */
}SctMemGuardReg;
/*
* SCT memory guard register start address
*/
#define SCT_MEM_GUARD_REG_ADDR (SCT_REG_ADDR + 0xEC)
/*
* SCT memory guard register pointer
*/
#define SCT_MEM_GUARD_CFG_REG ((SctMemGuardReg *)SCT_MEM_GUARD_REG_ADDR)
/******************************************************************************
******************************************************************************
* SCT channel state register
******************************************************************************
******************************************************************************/
/*
* SCT channel state register
* Bit WIDTH DESP
* 0:7 8 sct_cfg_fifo_idx_ch0, Channel next configure index
* a) reset/init value: 0
* b) increase 1, when chain triggered.
* c) Range: [0: fifoLen-1]
* 8:15 8 sct_done_fifo_idx_ch0, Channel next done index
* a) reset/init value: 0
* b) increase 1, when one chain process done.
* c) Range: [0: fifoLen-1]
* 16:23 8 sct_free_fifo_space_ch0
* Channel FIFO free space
* 24 1 sct_fifo_full_ch0
* Whether chain full (overflow), 0 - not, 1 - full
* 25 1 sct_fifo_empty_ch0
* Whether chain empty (all done), 0 - not, 1 - empty
* 26 1 sct_dscrpt_act_ch0
* Whether channel is activate, if descriptor in current channel is ongoing, then set 1, so only one channel could be set to 1
* 27 1 sct_rst_done_ch0, Whether channel reset done.
* a) SW: "SctChCtrlReg->chnReset" set 1, tigger SCT reset current channel
* b) HW: SCT should stop current descriptor, and ignore all the pending chain request
* c) HW: After reset done, SCT set this flag, and trigger ISR
* d) SW: when process this ISR, if need to write USB EP in this channel, need to reflush/reset USB
* e) HW: When this channel config/trigger again (SctChCtrlReg->chainTrg = 1), SCT clear this flag
* 28 1 sct_dscrpt_time_out_ch0, whether SCT process this descriptor time out
* a) HW: SCT start a guard timer, when start processing a descriptor, and stop it when done
* b) HW: When timeout, SCT set this flag, and trigger ISR
* c) HW: when SW reset current channel (SctChCtrlReg->chnReset = 1), SCT clear this flag
*
*
*/
typedef union
{
struct {
UINT32 chaNextCfgIdx : 8;
UINT32 chaNextDoneIdx : 8;
UINT32 chnFreeLen : 8;
UINT32 chnBeFull : 1;
UINT32 chnBeEmpty : 1;
UINT32 chnBeAct : 1;
UINT32 chnBeRstDone : 1;
UINT32 descBeTimeOut : 1;
UINT32 : 3;
};
UINT32 value32;
}SctChannelStateReg;
/*
* SCT channels state registers
*/
typedef struct
{
__I SctChannelStateReg chState[SCT_CHANNEL_NUM]; /* SCT channel state, read only, offset: 0x120 */
}SctCHSStateReg;
/*
* SCT channels state register start address
*/
#define SCT_CHS_STATE_REG_ADDR (SCT_REG_ADDR + 0x120)
/*
* SCT channels state register pointer
*/
#define SCT_CHS_STATE_REG ((SctCHSStateReg *)SCT_CHS_STATE_REG_ADDR)
/******************************************************************************
******************************************************************************
* SCT error status register
******************************************************************************
******************************************************************************/
/*
* SctErrStatusWord0 errStatus
* Bit WIDTH DESP
* 0:5 6 master error (AHB error)
* 6:11 6 memory guard error
* 12:17 6 descriptor info error (PPP/CRC not byte aligned)
*
*/
typedef union
{
struct {
UINT32 masterErr : 6;
UINT32 mgrErr : 6;
UINT32 descErr : 6;
UINT32 : 14;
};
UINT32 value32;
}SctErrStatusWord0;
/*
* SCT error status register struct
*/
typedef struct
{
__I SctErrStatusWord0 errStatus; /* sct_err_status, read only, offset: 0x138 */
__I UINT32 rdErrMem; /* sct_err_mpr_rd, SCT read error address, offset: 0x13C */
__I UINT32 wtErrMem; /* sct_err_mpr_wt, SCT write error address, offset: 0x140 */
}SctErrStatusReg;
/*
* SCT error status register start address
*/
#define SCT_ERR_STATUS_REG_ADDR (SCT_REG_ADDR + 0x138)
/*
* SCT error status register pointer
*/
#define SCT_ERR_STATUS_REG ((SctErrStatusReg *)SCT_ERR_STATUS_REG_ADDR)
#endif

View File

@@ -0,0 +1,282 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: timer.h
* Description: EC618 timer driver header file
* History:
*
****************************************************************************/
#ifndef _TIMER_EC618_H
#define _TIMER_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup timer_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief List of TIMER clock source */
typedef enum
{
TIMER_INTERNAL_CLOCK = 0U, /**< Internal clock */
TIMER_EXTERNAL_CLOCK = 1U, /**< External clock */
} TimerClockSource_t;
/** \brief List of TIMER match value select */
typedef enum
{
TIMER_MATCH0_SELECT = 0U, /**< Select Match0 */
TIMER_MATCH1_SELECT = 1U, /**< Select Match1 */
TIMER_MATCH2_SELECT = 2U, /**< Select Match2 */
} TimerMatchSelect_t;
/** \brief List of TIMER reload option, counter will be reloaded to init value upon reach it */
typedef enum
{
TIMER_RELOAD_DISABLE = 0U, /**< Counter will run freely */
TIMER_RELOAD_ON_MATCH0 = 1U, /**< Counter will be reloaded on reaching match0 value */
TIMER_RELOAD_ON_MATCH1 = 2U, /**< Counter will be reloaded on reaching match1 value */
TIMER_RELOAD_ON_MATCH2 = 3U, /**< Counter will be reloaded on reaching match1 value */
} TimerReloadOption_t;
/** \brief PWM configuration structure */
typedef struct
{
uint32_t pwmFreq_HZ; /**< PWM signal frequency in HZ */
uint32_t srcClock_HZ; /**< TIMER counter clock in HZ */
uint32_t dutyCyclePercent; /**< PWM pulse width, the valid range is 0 to 100 */
} TimerPwmConfig_t;
/** \brief TIMER configuration structure */
typedef struct
{
TimerClockSource_t clockSource; /**< Clock source */
TimerReloadOption_t reloadOption; /**< Reload option */
uint32_t initValue; /**< Counter init value */
uint32_t match0; /**< Match0 value */
uint32_t match1; /**< Match1 value */
uint32_t match2; /**< Match2 value */
} TimerConfig_t;
/** \brief TIMER interrupt configuration */
typedef enum
{
TIMER_INTERRUPT_DISABLED = 0U, /**< Disable interrupt */
TIMER_INTERRUPT_LEVEL = 1U, /**< Level interrupt, a high level interrupt signal is generated */
TIMER_INTERRUPT_PULSE = 2U, /**< Pulse interrupt, a pulse of one clock width
is generated after counter matches */
} TimerInterruptConfig_t;
/** \brief List of TIMER interrupts */
typedef enum
{
TIMER_MATCH0_INTERRUPT_ENABLE = TIMER_TCTLR_IE_0_Msk, /**< Match0 interrupt */
TIMER_MATCH1_INTERRUPT_ENABLE = TIMER_TCTLR_IE_1_Msk, /**< Match1 interrupt */
TIMER_MATCH2_INTERRUPT_ENABLE = TIMER_TCTLR_IE_2_Msk, /**< Match2 interrupt */
} TimerInterruptEnable_t;
/** \brief List of TIMER interrupt flags */
typedef enum
{
TIMER_MATCH0_INTERRUPT_FLAG = TIMER_TSR_ICLR_0_Msk, /**< Match0 interrupt flag */
TIMER_MATCH1_INTERRUPT_FLAG = TIMER_TSR_ICLR_1_Msk, /**< Match1 interrupt flag */
TIMER_MATCH2_INTERRUPT_FLAG = TIMER_TSR_ICLR_2_Msk, /**< Match2 interrupt flag */
} TimerInterruptFlags_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name TIMER Driver Initialization */
/** \{ */
/**
\fn void TIMER_driverInit(void);
\brief Intialize TIMER driver internal data, must be called before any other APIs
*/
void TIMER_driverInit(void);
/** \} */
/** \name TIMER Configuration */
/** \{ */
/**
\fn void TIMER_getDefaultConfig(TimerConfig_t *config)
\brief Gets the TIMER default configuartion.
This function sets the configuration structure to default values as below:
\code
config->clockSource = TIMER_INTERNAL_CLOCK;
config->reloadOption = TIMER_RELOAD_ON_MATCH1;
config->initValue = 0;
config->match0 = 0x10000 >> 1;
config->match1 = 0x10000;
config->match2 = 0xFFFFFFFF;
\endcode
\param[in] config Pointer to TIMER configuration structure
*/
void TIMER_getDefaultConfig(TimerConfig_t *config);
/**
\fn void TIMER_init(uint32_t instance, const TimerConfig_t *config)
\brief Intialize TIMER
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] config Pointer to TIMER configuration
\note PWM out is disabled after this function's call, use \ref TIMER_setupPwm function to eable PWM
*/
void TIMER_init(uint32_t instance, const TimerConfig_t *config);
/**
\fn void TIMER_deInit(uint32_t instance)
\brief Deintialize TIMER
\param[in] instance TIMER instance number (0, 1, ...)
*/
void TIMER_deInit(uint32_t instance);
/**
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
\brief Sets one of TIMER match values
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] matchNum TIMER match select
\param[in] matchValue TIMER match value
*/
void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t matchNum, uint32_t matchValue);
/**
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
\brief Sets TIMER counter initial value
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] initValue TIMER initial value
*/
void TIMER_setInitValue(uint32_t instance, uint32_t initValue);
/**
\fn void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t match)
\brief Sets TIMER counter reload option
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] option TIMER counter reload option
*/
void TIMER_setReloadOption(uint32_t instance, TimerReloadOption_t option);
/** \} */
/** \name TIMER Counter */
/** \{ */
/**
\fn void TIMER_start(uint32_t instance)
\brief Starts TIMER counter
\param[in] instance TIMER instance number (0, 1, ...)
*/
void TIMER_start(uint32_t instance);
/**
\fn void TIMER_stop(uint32_t instance)
\brief Stops TIMER counter
\param[in] instance TIMER instance number (0, 1, ...)
*/
void TIMER_stop(uint32_t instance);
/**
\fn uint32_t TIMER_getCount(uint32_t instance)
\brief Reads current TIMER counter value
\param[in] instance TIMER instance number (0, 1, ...)
\return current TIMER counter value
*/
uint32_t TIMER_getCount(uint32_t instance);
/** \} */
/** \name TIMER PWM */
/** \{ */
/**
\fn int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config)
\brief Configures the PWM signals period, mode, etc.
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] config Pointer to PWM parameter
\return ARM_DRIVER_OK if the PWM setup is successful
ARM_DRIVER_ERROR_PARAMETER on parameter check failure
*/
int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config);
/**
\fn void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent)
\brief Updates the duty cycle of PWM signal
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] dutyCyclePercent New PWM pulse width, value shall be between 0 to 100,
if the value exceeds 100, dutyCyclePercent is set to 100.
*/
void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent);
/** \} */
/** \name TIMER Interrupt */
/** \{ */
/**
\fn void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config)
\brief Configures the selected TIMER interrupt
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] match TIMER match select
\param[in] config TIMER interrupt configuration
*/
void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config);
/**
\fn TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match)
\brief Gets current configuration of the selected TIMER interrupt
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] match TIMER match select
\return Current TIMER interrupt configuration
*/
TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match);
/**
\fn uint32_t TIMER_getInterruptFlags(uint32_t instance)
\brief Reads TIMER interrupt status flags
\param[in] instance TIMER instance number (0, 1, ...)
\return Interrupt flags. This is the logical OR of members of the
enumeration \ref TimerInterruptFlags_t
*/
uint32_t TIMER_getInterruptFlags(uint32_t instance);
/**
\fn void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask)
\brief Clears TIMER interrupt flags
\param[in] instance TIMER instance number (0, 1, ...)
\param[in] mask Interrupt flags to clear. This is a logic OR of members of the
enumeration \ref TimerInterruptFlags_t
*/
void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask);
/**
\fn void TIMER_netlightEnable(uint32_t instance)
\brief Set Netlight Enable, called by user in bsp_custom.c to define specific timer instance for netlight
\param[in] instance TIMER instance number (0, 1, ...)
*/
void TIMER_netlightEnable(uint8_t instance);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _TIMER_EC618_H */

View File

@@ -0,0 +1,259 @@
#ifndef __TLS_H__
#define __TLS_H__
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
#define SCT_BASE_ADDR (0x40050000)
#define AES_SHA_CH4_CFG_REG (SCT_BASE_ADDR + 0xbc) // AES/SHA uses sct channel4
#define AES_SHA_CH4_STATE_REG (SCT_BASE_ADDR + 0x130)
#define SCT_ENABLE_REG (SCT_BASE_ADDR + 0x00)
#define SCT_COMM_CFG0_REG (SCT_BASE_ADDR + 0x54)
#define SCT_COMM_CFG1_REG (SCT_BASE_ADDR + 0x58)
#define SCT_MEM_GUARD_REG (SCT_BASE_ADDR + 0xec)
typedef enum
{
SHA_TYPE_1,
SHA_TYPE_224,
SHA_TYPE_256,
}shaType_e;
typedef struct
{
uint32_t length : 16;
uint32_t dir : 1; // 0 - Encryption, 1 - Decryption
uint32_t aesMode : 2; // 0 <20>C ECB, 1 <20>C CBC, 2 <20>C CTR
uint32_t paddingMode : 3;
uint32_t ckLen : 2; // 0 <20>C 128, 1 <20>C 192, 2 <20>C 256
uint32_t aesCkSel : 1; // 0 <20>C from configured CK address, 1 <20>C from efuse
uint32_t : 2;
uint32_t subType : 2; // 0 <20>C AES descriptor; 1 <20>C SHA descriptor
uint32_t type : 3; // Default 101
}aesField_t;
typedef struct
{
uint32_t length : 16; // sha can handle 64k data one time
uint32_t shaMode : 2; // 0: sha1; 1: sha224; 2: sha256
uint32_t shaBls : 1; // sha output endian. 0: LE; 1: BE
uint32_t rcs : 1; // 0: current is last data; 1: current data is continuous
uint32_t outEn : 1; // open output
uint32_t : 6;
uint32_t subType : 2; // // 0: aes; 1:sha
uint32_t type : 3; // Default 101
}shaField_t;
typedef struct
{
uint32_t headLen : 16;
uint32_t : 16;
}shaHeadLen_t;
typedef struct
{
union firstWord
{
aesField_t aesField;
shaField_t shaField;
}u1;
uint32_t srcAddr;
uint32_t dstAddr;
union secondWord
{
uint32_t aesCkAddr;
uint32_t shaHeaderAddr;
}u2;
union thirdWord
{
uint32_t aesIvAddr;
shaHeadLen_t shaHeadLen;
}u3;
}sctDescCfg_t;
typedef struct
{
uint32_t trigger : 1;
uint32_t reset : 1;
uint32_t : 30;
}sctChanCfg_t;
typedef union {
struct
{
uint32_t fifoLen : 8; // chain fifo length, max is 255
uint32_t chainIntEn : 1;
uint32_t chainEmptyIntEn : 1;
uint32_t chainFullIntEn : 1;
uint32_t ckBLEndian : 1;
uint32_t aesIvBLEndian : 1; // bit: 12
uint32_t ckOptDis : 1; // bit: 13
uint32_t : 2;
uint32_t crcPolyLen : 2; // bit: 16:17
uint32_t : 1;
uint32_t crcOutComple : 1; // bit: 19
uint32_t crcInCompleByteNum: 4; // bit: 20:23
uint32_t crcOutBitSwap : 1; // bit: 24
uint32_t crcInBitSwap : 1; // bit: 25
uint32_t : 6;
};
uint32_t val;
}chanCfgWord0_t;
typedef struct
{
chanCfgWord0_t chanCfgWord0;
uint32_t chanCfgWord1; // First desc addr
uint32_t rsvd[3];
sctChanCfg_t chanCfgWord5;
}sctCfgWord_t;
typedef struct
{
uint32_t chaNextCfgIdx : 8;
uint32_t chaNextDoneIdx : 8;
uint32_t chaFreeLen : 8;
uint32_t chaBeFull : 1;
uint32_t chaBeEmpty : 1;
uint32_t chaBeAct : 1;
uint32_t chaBeRstDone : 1;
uint32_t descBeTimeout : 1;
uint32_t : 3;
}sctChaState_t;
typedef struct
{
uint32_t hAddr0;
uint32_t lAddr0;
uint32_t hAddr1;
uint32_t lAddr1;
uint32_t hAddr2;
uint32_t lAddr2;
uint32_t hAddr3;
uint32_t lAddr3;
}sctMemGuard_t;
typedef union
{
struct
{
uint32_t rmiAcg : 1;
uint32_t ahbAcg : 1;
uint32_t : 14;
uint32_t chainStartUnilog : 1;
uint32_t descDoneUnilog : 1;
uint32_t chainEndUnilog : 1;
uint32_t errorIntUnilog : 1;
uint32_t usbEndianInd : 1;
uint32_t : 3;
uint32_t memHighAddrOffset : 8;
};
uint32_t val;
}sctCfgWord0_t;
typedef struct
{
uint32_t descMaxProcTickTime : 20; // descriptor handle max timeout
uint32_t : 12;
}sctCfgWord1_t;
typedef struct
{
uint32_t dir : 1; // 0: encrypt, 1: decrypt
uint32_t aesMode : 2; // 0: ecb, 1:cbc, 2:ctr
uint32_t paddingMode : 3; // 0: no padding, 1: PKCS7, 2: paddingOneZeros, 3: paddingZerosLen, 4: paddingZeros
uint32_t ckLen : 2; // 0:128, 1:192, 2:256
uint32_t aesCkSel : 1; // 0: from memory, 1: from efuse
uint32_t ckBLEndian : 1; // Ignore it if key is from efuse. If key is from memory, 0: little; 1: big
uint32_t aesIvBLEndian : 1; // input AES IV is big/little endian. 0: little; 1: big
uint32_t : 23;
}aesCtrl_t;
typedef struct
{
uint32_t ivAddr;
uint32_t srcAddr;
uint32_t dstAddr;
uint32_t aesCkAddr;
uint32_t length;
aesCtrl_t aesCtrl;
}aesInfo_t;
/*
* SCT memory guard address
* SCT could only access MSMB: 0x00400000 ~ 0x0053FFFF
*/
#define MGR_LOW_ADDR 0x00400000
#define MGR_HIGH_ADDR 0x0053FFFF
/*
* SCT memory guard address
* USB TX FIFO: 0x00400000 ~ 0x0053FFFF
*/
#define MGR_LOW_ADDR1 0x1A000000
#define MGR_HIGH_ADDR1 0x1AFFFFFF
/*
* AP flash, 4M: 0x0080-0000~0x00BF-FFFF
*/
#define MGR_LOW_ADDR2 0x00800000
#define MGR_HIGH_ADDR2 0x00BFFFFF
/*
* CP flash, 1M: 0x0880-0000~0x088F-FFFF
*/
#define MGR_LOW_ADDR3 0x08800000
#define MGR_HIGH_ADDR3 0x088FFFFF
#define SCTDRV_OK (0)
#define SCTDRV_BUSY (-1)
#define SCTDRV_TIMEOUT (-2)
#define SCTDRV_PAMERR (-5)
/**
\brief SCT module init.
\return
*/
void sctInit();
/**
\brief SCT module deInit.
\return
*/
void sctDeInit();
/**
\brief Aes operation
\param[in] aesInfo Aes information.
\return status
*/
int32_t aesUpdate(aesInfo_t* aesInfo);
/**
\brief Sha operation.
\param[in] shaMode Choose SHA1, SHA224, SHA256.
\param[in] srcAddr SHA input address.
\param[in] dstAddr SHA output address.
\param[in] length SHA input length.
\param[in] lastFlag If you need to loop call this api, "lastFlag" should be 0 for intermediate steps, and last step it should be 1.
\return status
*/
int32_t shaUpdate(shaType_e shaMode, uint32_t srcAddr, uint32_t dstAddr, uint32_t length, uint32_t lastFlag);
#endif

View File

@@ -0,0 +1,83 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: uart.h
* Description: EC618 uart driver header file
* History:
*
****************************************************************************/
#ifndef _UART_EC618_H
#define _UART_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup uart_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/**
\fn void UART_init(uint32_t instance, uint32_t baudrate, bool enableFlowCtrl)
\brief Initialize UART with specific baudrate
\param[in] instance UART instance number (0, 1, ...)
\param[in] baudrate The desired baudrate
\param[in] enableFlowCtrl Enable flow control or not
*/
void UART_init(uint32_t instance, uint32_t baudrate, bool enableFlowCtrl);
/**
\fn uint32_t UART_send(uint32_t instance, const uint8_t *data, uint32_t num, uint32_t timeout_us)
\brief Start sending data to USART transmitter in polling way
\param[in] instance UART instance number (0, 1, ...)
\param[in] data Pointer to buffer with data to send to USART transmitter
\param[in] num Number of data items to send
\param[in] timeout_us timeout value in unit of us
\return num of data items sent in the internal of timeout
*/
uint32_t UART_send(uint32_t instance, const uint8_t *data, uint32_t num, uint32_t timeout_us);
/**
\fn uint32_t UART_receive(uint32_t instance, uint8_t *data, uint32_t num, uint32_t timeout_us)
\brief Start receiving data from USART receiver in polling way
\param[in] instance UART instance number (0, 1, ...)
\param[out] data Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to receive
\param[in] timeout_us timeout value in unit of us
\return num of data items received in the internal of timeout
*/
uint32_t UART_receive(uint32_t instance, uint8_t *data, uint32_t num, uint32_t timeout_us);
/**
\fn void UART_printf(uint32_t instance, const char* fmt, ...)
\brief Print formated data to USART transmitter
\param[in] instance UART instance number (0, 1, ...)
\param[in] fmt C string that contains the text to be sent to UART
\param[in] ... __VA__ARGS
*/
void UART_printf(uint32_t instance, const char* fmt, ...);
void UART_flush(uint32_t instance);
void UART_purgeRx(uint32_t instance);
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _UART_EC618_H */

View File

@@ -0,0 +1,83 @@
/******************************************************************************
*(C) Copyright 2018 AirM2M International Ltd.
* All Rights Reserved
******************************************************************************
* Filename:
*
* Description:
*
* History:
*
* Notes:
*
******************************************************************************/
#ifndef _UNILOG_API_H
#define _UNILOG_API_H
/*----------------------------------------------------------------------------*
* INCLUDES *
*----------------------------------------------------------------------------*/
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*
* MACROS *
*----------------------------------------------------------------------------*/
#define UNILOG_TRACE_MAX_MODULE_VALUE (1024)
#define UNILOG_DMA_REQ_MODE_USB (0x3)
#define UNILOG_DMA_REQ_MODE_UART (0x0)
#define UNILOG_ID_CONSTRUCT(ownerId, moduleId, subId) ((ownerId << 28) | (moduleId << 21) | (subId << 11))
/*----------------------------------------------------------------------------*
* DATA TYPE DEFINITION *
*----------------------------------------------------------------------------*/
typedef enum
{
UART_0_FOR_UNILOG = 0,
UART_1_FOR_UNILOG = 1,
UART_2_FOR_UNILOG = 2,
// SPI_0_FOR_UNILOG = 3,
// SPI_1_FOR_UNILOG = 4,
USB_FOR_UNILOG = 5
} UnilogPeripheralType_e;
/*----------------------------------------------------------------------------*
* GLOBAL FUNCTIONS DECLEARATION *
*----------------------------------------------------------------------------*/
void uniLogModuleAllowTraces(uint16_t moduleID);
void uniLogModuleDisableTraces(uint16_t moduleID);
void uniLogModuleAllowAllTraces(void);
void uniLogModuleDisableAllTraces(void);
bool uniLogTraceAllowCheck(uint8_t debugLevel);
void uniLogFlushOut(void);
void uniLogForceOut(bool waitFifoOut);
void uniLogStop(void);
void uniLogStopHwLog(void);
bool uniLogIsInitialized(void);
void uniLogGetSettingFromFlash(void);
void swLogExcep(uint32_t swLogID, uint8_t debugLevel, ...);
void swLogPrintf(uint32_t swLogID, uint8_t debugLevel, ...);
void swLogDump(uint32_t swLogID, uint8_t debugLevel, uint32_t dumpLen, const uint8_t*pDump);
void swLogPrintfPolling(uint32_t swLogID, uint8_t debugLevel, ...);
void swLogDumpPolling(uint32_t swLogID, uint8_t debugLevel, uint32_t dumpLen, const uint8_t*pDump);
void uniLogSetPherType(UnilogPeripheralType_e periphType);
UnilogPeripheralType_e uniLogGetPherType(void);
bool unilogSwitch2UartLog(void);
bool unilogSwitch2UsbLog(void);
bool uniLogGetDumpRdyFlag(void);
#ifdef __cplusplus
}
#endif
#endif//_UNILOG_API_H

View File

@@ -0,0 +1,160 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: wdt.h
* Description: EC618 wdt driver header file
* History:
*
****************************************************************************/
#ifndef _WDT_EC618_H
#define _WDT_EC618_H
#include "ec618.h"
#include "Driver_Common.h"
/**
\addtogroup wdt_interface_gr
\{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/** \brief List of WDT mode */
typedef enum
{
WDT_INTERRUPT_ONLY_MODE = 0U, /**< Only generate an interrupt upon timeout */
WDT_INTERRUPT_RESET_MODE = 1U, /**< Reset upon timeout if the first interrupt is not cleared */
} WdtMode_e;
/** \brief WDT configuration structure */
typedef struct
{
WdtMode_e mode;
uint16_t timeoutValue;
} WdtConfig_t;
/** \brief List of WDT interrupt flags */
typedef enum
{
WDT_INTERRUPT_FLAG = WDT_STAT_ISTAT_Msk, /**< Wdt interrupt flag */
} WdtInterruptFlags_e;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/** \name WDT Configuration */
/** \{ */
/**
\fn void WDT_getDefaultConfig(WdtConfig_t *config)
\brief Gets the WDT default configuartion.
This function sets the configuration structure to default values as below:
\code
config->mode = WDT_INTERRUPT_ONLY_MODE;
config->timeoutValue = 0xFFFF;
\endcode
\param[in] config Pointer to WDT configuration structure
*/
void WDT_getDefaultConfig(WdtConfig_t *config);
/**
\fn void WDT_init(const WdtConfig_t *config)
\brief Initialize WDT
\param[in] config Pointer to WDT configuration
*/
void WDT_init(const WdtConfig_t *config);
/**
\fn void WDT_deInit(void)
\brief Deinitialize WDT
*/
void WDT_deInit(void);
/** \} */
/** \name WDT Unlock and Kick */
/** \{ */
/**
\fn void WDT_unlock(void)
\brief Unlocks the WDT register written
*/
void WDT_unlock(void);
/**
\fn void WDT_kick(void)
\brief Refreshes WDT counter
*/
void WDT_kick(void);
/** \} */
/** \name WDT Start and Stop */
/** \{ */
/**
\fn void WDT_start(void)
\brief Starts WDT counter
*/
void WDT_start(void);
/**
\fn void WDT_stop(void)
\brief Stops WDT counter
*/
void WDT_stop(void);
/** \} */
/** \name WDT Interrupt and Status */
/** \{ */
/**
\fn uint32_t WDT_getInterruptFlags(void)
\brief Reads WDT interrupt status flags
\return Interrupt flags. This is the logical OR of members of the
enumeration \ref WdtInterruptFlags_e
*/
uint32_t WDT_getInterruptFlags(void);
/**
\fn void WDTclearInterruptFlags(uint32_t mask)
\brief Clears WDT interrupt flags
\param[in] mask Interrupt flags to clear. This is a logic OR of members of the
enumeration \ref WdtInterruptFlags_e
*/
void WDTclearInterruptFlags(uint32_t mask);
/**
\fn WdtMode_e WDT_getMode(void)
\brief Gets current WDT mode
\return WDT mode, see \ref WdtMode_e
*/
WdtMode_e WDT_getMode(void);
/**
\fn bool WDT_getStartStatus(void)
\brief Checks if WDT is started or stopped
\return true if WDT is counting
false if WDT is stopped
*/
bool WDT_getStartStatus(void);
/** \} */
/** \} */
#ifdef __cplusplus
}
#endif
#endif /* _WDT_EC618_H */

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Feb 2017
* $Revision: V2.0
*
* Project: Common Driver definitions
*/
/* History:
* Version 2.0
* Changed prefix ARM_DRV -> ARM_DRIVER
* Added General return codes definitions
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.00
* Initial release
*/
#ifndef DRIVER_COMMON_H_
#define DRIVER_COMMON_H_
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "sctdef.h"
#ifdef FEATURE_OS_ENABLE
#include "exception_process.h"
#endif
#define ARM_DRIVER_VERSION_MAJOR_MINOR(major,minor) (((major) << 8) | (minor))
/**
\brief Driver Version
*/
typedef struct _ARM_DRIVER_VERSION {
uint16_t api; ///< API version
uint16_t drv; ///< Driver version
} ARM_DRIVER_VERSION;
/* General return codes */
#define ARM_DRIVER_OK 0 ///< Operation succeeded
#define ARM_DRIVER_ERROR -1 ///< Unspecified error
#define ARM_DRIVER_ERROR_BUSY -2 ///< Driver is busy
#define ARM_DRIVER_ERROR_TIMEOUT -3 ///< Timeout occurred
#define ARM_DRIVER_ERROR_UNSUPPORTED -4 ///< Operation not supported
#define ARM_DRIVER_ERROR_PARAMETER -5 ///< Parameter error
#define ARM_DRIVER_ERROR_SPECIFIC -6 ///< Start of driver specific errors
/**
\brief General power states
*/
typedef enum _ARM_POWER_STATE {
ARM_POWER_OFF, ///< Power off: no operation possible
ARM_POWER_LOW, ///< Low Power mode: retain state, detect and signal wake-up events
ARM_POWER_FULL ///< Power on: full operation at maximum performance
} ARM_POWER_STATE;
typedef struct _PIN {
uint8_t pinNum;
uint8_t funcNum;
} PIN;
#ifndef ASSERT
#ifdef FEATURE_OS_ENABLE
#define ASSERT(X) EC_ASSERT(X,0,0,0)
#else
#define ASSERT(X) assert(X)
#endif
#endif
#ifndef BIT
#define BIT(n) ((unsigned int) 1 << (n))
#define BITS2(m,n) (BIT(m) | BIT(n))
#define BITS(m,n) (~(BIT(m) - 1) & ((BIT(n) - 1) | BIT(n)))
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b) ? (a) : (b)))
#endif
#endif /* DRIVER_COMMON_H_ */

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Feb 2017
* $Revision: V2.3
*
* Project: I2C (Inter-Integrated Circuit) Driver definitions
*/
/* History:
* Version 2.3
* ARM_I2C_STATUS made volatile
* Version 2.2
* Removed function ARM_I2C_MasterTransfer in order to simplify drivers
* and added back parameter "xfer_pending" to functions
* ARM_I2C_MasterTransmit and ARM_I2C_MasterReceive
* Version 2.1
* Added function ARM_I2C_MasterTransfer and removed parameter "xfer_pending"
* from functions ARM_I2C_MasterTransmit and ARM_I2C_MasterReceive
* Added function ARM_I2C_GetDataCount
* Removed flag "address_nack" from ARM_I2C_STATUS
* Replaced events ARM_I2C_EVENT_MASTER_DONE and ARM_I2C_EVENT_SLAVE_DONE
* with event ARM_I2C_EVENT_TRANSFER_DONE
* Added event ARM_I2C_EVENT_TRANSFER_INCOMPLETE
* Removed parameter "arg" from function ARM_I2C_SignalEvent
* Version 2.0
* New simplified driver:
* complexity moved to upper layer (especially data handling)
* more unified API for different communication interfaces
* Added:
* Slave Mode
* Changed prefix ARM_DRV -> ARM_DRIVER
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.00
* Initial release
*/
#ifndef DRIVER_I2C_H_
#define DRIVER_I2C_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "Driver_Common.h"
#define ARM_I2C_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,3) /* API version */
/****** I2C Control Codes *****/
#define ARM_I2C_OWN_ADDRESS (0x01) ///< Set Own Slave Address; arg = address
#define ARM_I2C_BUS_SPEED (0x02) ///< Set Bus Speed; arg = speed
#define ARM_I2C_BUS_CLEAR (0x03) ///< Execute Bus clear: send nine clock pulses
#define ARM_I2C_ABORT_TRANSFER (0x04) ///< Abort Master/Slave Transmit/Receive
/*----- I2C Bus Speed -----*/
#define ARM_I2C_BUS_SPEED_STANDARD (0x01) ///< Standard Speed (100kHz)
#define ARM_I2C_BUS_SPEED_FAST (0x02) ///< Fast Speed (400kHz)
#define ARM_I2C_BUS_SPEED_FAST_PLUS (0x03) ///< Fast+ Speed ( 1MHz)
#define ARM_I2C_BUS_SPEED_HIGH (0x04) ///< High Speed (3.4MHz)
/****** I2C Address Flags *****/
#define ARM_I2C_ADDRESS_10BIT (0x0400) ///< 10-bit address flag
#define ARM_I2C_ADDRESS_GC (0x8000) ///< General Call flag
/**
\brief I2C Status
*/
typedef volatile struct _ARM_I2C_STATUS {
uint32_t busy : 1; ///< Busy flag
uint32_t mode : 1; ///< Mode: 0=Slave, 1=Master
uint32_t direction : 1; ///< Direction: 0=Transmitter, 1=Receiver
uint32_t general_call : 1; ///< General Call indication (cleared on start of next Slave operation)
uint32_t arbitration_lost : 1; ///< Master lost arbitration (cleared on start of next Master operation)
uint32_t bus_error : 1; ///< Bus error detected (cleared on start of next Master/Slave operation)
uint32_t rx_nack : 1; ///< NACK detected (cleared on start of next Master/Slave operation)
uint32_t reserved : 25;
} ARM_I2C_STATUS;
/****** I2C Event *****/
#define ARM_I2C_EVENT_TRANSFER_DONE (1UL << 0) ///< Master/Slave Transmit/Receive finished
#define ARM_I2C_EVENT_TRANSFER_INCOMPLETE (1UL << 1) ///< Master/Slave Transmit/Receive incomplete transfer
#define ARM_I2C_EVENT_SLAVE_TRANSMIT (1UL << 2) ///< Addressed as Slave Transmitter but transmit operation is not set.
#define ARM_I2C_EVENT_SLAVE_RECEIVE (1UL << 3) ///< Addressed as Slave Receiver but receive operation is not set.
#define ARM_I2C_EVENT_ADDRESS_NACK (1UL << 4) ///< Address not acknowledged from Slave
#define ARM_I2C_EVENT_GENERAL_CALL (1UL << 5) ///< Slave addressed with general call address
#define ARM_I2C_EVENT_ARBITRATION_LOST (1UL << 6) ///< Master lost arbitration
#define ARM_I2C_EVENT_BUS_ERROR (1UL << 7) ///< Bus error detected (START/STOP at illegal position)
#define ARM_I2C_EVENT_BUS_CLEAR (1UL << 8) ///< Bus clear finished
// Function documentation
/**
\fn ARM_DRIVER_VERSION ARM_I2C_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn ARM_I2C_CAPABILITIES ARM_I2C_GetCapabilities (void)
\brief Get driver capabilities.
\return \ref ARM_I2C_CAPABILITIES
\fn int32_t ARM_I2C_Initialize (ARM_I2C_SignalEvent_t cb_event)
\brief Initialize I2C Interface.
\param[in] cb_event Pointer to \ref ARM_I2C_SignalEvent
\return \ref execution_status
\fn int32_t ARM_I2C_Uninitialize (void)
\brief De-initialize I2C Interface.
\return \ref execution_status
\fn int32_t ARM_I2C_PowerControl (ARM_POWER_STATE state)
\brief Control I2C Interface Power.
\param[in] state Power state
\return \ref execution_status
\fn int32_t ARM_I2C_MasterTransmit (uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending)
\brief Start transmitting data as I2C Master.
\param[in] addr Slave address (7-bit or 10-bit)
\param[in] data Pointer to buffer with data to transmit to I2C Slave
\param[in] num Number of data bytes to transmit
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
\return \ref execution_status
\fn int32_t ARM_I2C_MasterReceive (uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending)
\brief Start receiving data as I2C Master.
\param[in] addr Slave address (7-bit or 10-bit)
\param[out] data Pointer to buffer for data to receive from I2C Slave
\param[in] num Number of data bytes to receive
\param[in] xfer_pending Transfer operation is pending - Stop condition will not be generated
\return \ref execution_status
\fn int32_t ARM_I2C_SlaveTransmit (const uint8_t *data, uint32_t num)
\brief Start transmitting data as I2C Slave.
\param[in] data Pointer to buffer with data to transmit to I2C Master
\param[in] num Number of data bytes to transmit
\return \ref execution_status
\fn int32_t ARM_I2C_SlaveReceive (uint8_t *data, uint32_t num)
\brief Start receiving data as I2C Slave.
\param[out] data Pointer to buffer for data to receive from I2C Master
\param[in] num Number of data bytes to receive
\return \ref execution_status
\fn int32_t ARM_I2C_GetDataCount (void)
\brief Get transferred data count.
\return number of data bytes transferred; -1 when Slave is not addressed by Master
\fn int32_t ARM_I2C_Control (uint32_t control, uint32_t arg)
\brief Control I2C Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\return \ref execution_status
\fn ARM_I2C_STATUS ARM_I2C_GetStatus (void)
\brief Get I2C status.
\return I2C status \ref ARM_I2C_STATUS
\fn void ARM_I2C_SignalEvent (uint32_t event)
\brief Signal I2C Events.
\param[in] event \ref I2C_events notification mask
*/
typedef void (*ARM_I2C_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_I2C_SignalEvent : Signal I2C Event.
/**
\brief I2C Driver Capabilities.
*/
typedef struct _ARM_I2C_CAPABILITIES {
uint32_t address_10_bit : 1; ///< supports 10-bit addressing
uint32_t reserved : 31; ///< Reserved (must be zero)
} ARM_I2C_CAPABILITIES;
/**
\brief Access structure of the I2C Driver.
*/
typedef struct _ARM_DRIVER_I2C {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_I2C_GetVersion : Get driver version.
ARM_I2C_CAPABILITIES (*GetCapabilities)(void); ///< Pointer to \ref ARM_I2C_GetCapabilities : Get driver capabilities.
int32_t (*Initialize) (ARM_I2C_SignalEvent_t cb_event); ///< Pointer to \ref ARM_I2C_Initialize : Initialize I2C Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_I2C_Uninitialize : De-initialize I2C Interface.
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_I2C_PowerControl : Control I2C Interface Power.
int32_t (*MasterTransmit) (uint32_t addr, const uint8_t *data, uint32_t num, bool xfer_pending); ///< Pointer to \ref ARM_I2C_MasterTransmit : Start transmitting data as I2C Master.
int32_t (*MasterReceive) (uint32_t addr, uint8_t *data, uint32_t num, bool xfer_pending); ///< Pointer to \ref ARM_I2C_MasterReceive : Start receiving data as I2C Master.
int32_t (*SlaveTransmit) ( const uint8_t *data, uint32_t num); ///< Pointer to \ref ARM_I2C_SlaveTransmit : Start transmitting data as I2C Slave.
int32_t (*SlaveReceive) ( uint8_t *data, uint32_t num); ///< Pointer to \ref ARM_I2C_SlaveReceive : Start receiving data as I2C Slave.
int32_t (*GetDataCount) (void); ///< Pointer to \ref ARM_I2C_GetDataCount : Get transferred data count.
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_I2C_Control : Control I2C Interface.
ARM_I2C_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_I2C_GetStatus : Get I2C status.
} const ARM_DRIVER_I2C;
#ifdef __cplusplus
}
#endif
#endif /* DRIVER_I2C_H_ */

View File

@@ -0,0 +1,247 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Feb 2017
* $Revision: V2.2
*
* Project: SPI (Serial Peripheral Interface) Driver definitions
*/
/* History:
* Version 2.2
* ARM_SPI_STATUS made volatile
* Version 2.1
* Renamed status flag "tx_rx_busy" to "busy"
* Version 2.0
* New simplified driver:
* complexity moved to upper layer (especially data handling)
* more unified API for different communication interfaces
* Added:
* Slave Mode
* Half-duplex Modes
* Configurable number of data bits
* Support for TI Mode and Microwire
* Changed prefix ARM_DRV -> ARM_DRIVER
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.01
* Added "send_done_event" to Capabilities
* Version 1.00
* Initial release
*/
#ifndef DRIVER_SPI_H_
#define DRIVER_SPI_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "Driver_Common.h"
#define ARM_SPI_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,2) /* API version */
/****** SPI Control Codes *****/
#define ARM_SPI_CONTROL_Pos 0
#define ARM_SPI_CONTROL_Msk (0xFFUL << ARM_SPI_CONTROL_Pos)
/*----- SPI Control Codes: Mode -----*/
#define ARM_SPI_MODE_INACTIVE (0x00UL << ARM_SPI_CONTROL_Pos) ///< SPI Inactive
#define ARM_SPI_MODE_MASTER (0x01UL << ARM_SPI_CONTROL_Pos) ///< SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps
#define ARM_SPI_MODE_SLAVE (0x02UL << ARM_SPI_CONTROL_Pos) ///< SPI Slave (Output on MISO, Input on MOSI)
#define ARM_SPI_MODE_MASTER_SIMPLEX (0x03UL << ARM_SPI_CONTROL_Pos) ///< SPI Master (Output/Input on MOSI); arg = Bus Speed in bps
#define ARM_SPI_MODE_SLAVE_SIMPLEX (0x04UL << ARM_SPI_CONTROL_Pos) ///< SPI Slave (Output/Input on MISO)
/*----- SPI Control Codes: Mode Parameters: Frame Format -----*/
#define ARM_SPI_FRAME_FORMAT_Pos 8
#define ARM_SPI_FRAME_FORMAT_Msk (7UL << ARM_SPI_FRAME_FORMAT_Pos)
#define ARM_SPI_CPOL0_CPHA0 (0UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 0, Clock Phase 0 (default)
#define ARM_SPI_CPOL0_CPHA1 (1UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 0, Clock Phase 1
#define ARM_SPI_CPOL1_CPHA0 (2UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 1, Clock Phase 0
#define ARM_SPI_CPOL1_CPHA1 (3UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Clock Polarity 1, Clock Phase 1
#define ARM_SPI_TI_SSI (4UL << ARM_SPI_FRAME_FORMAT_Pos) ///< Texas Instruments Frame Format
#define ARM_SPI_MICROWIRE (5UL << ARM_SPI_FRAME_FORMAT_Pos) ///< National Microwire Frame Format
/*----- SPI Control Codes: Mode Parameters: Data Bits -----*/
#define ARM_SPI_DATA_BITS_Pos 12
#define ARM_SPI_DATA_BITS_Msk (0x3FUL << ARM_SPI_DATA_BITS_Pos)
#define ARM_SPI_DATA_BITS(n) (((n) & 0x3F) << ARM_SPI_DATA_BITS_Pos) ///< Number of Data bits
/*----- SPI Control Codes: Mode Parameters: Bit Order -----*/
#define ARM_SPI_BIT_ORDER_Pos 18
#define ARM_SPI_BIT_ORDER_Msk (1UL << ARM_SPI_BIT_ORDER_Pos)
#define ARM_SPI_MSB_LSB (0UL << ARM_SPI_BIT_ORDER_Pos) ///< SPI Bit order from MSB to LSB (default)
#define ARM_SPI_LSB_MSB (1UL << ARM_SPI_BIT_ORDER_Pos) ///< SPI Bit order from LSB to MSB
/*----- SPI Control Codes: Mode Parameters: Slave Select Mode -----*/
#define ARM_SPI_SS_MASTER_MODE_Pos 19
#define ARM_SPI_SS_MASTER_MODE_Msk (3UL << ARM_SPI_SS_MASTER_MODE_Pos)
#define ARM_SPI_SS_MASTER_UNUSED (0UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Not used (default)
#define ARM_SPI_SS_MASTER_SW (1UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Software controlled
#define ARM_SPI_SS_MASTER_HW_OUTPUT (2UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Hardware controlled Output
#define ARM_SPI_SS_MASTER_HW_INPUT (3UL << ARM_SPI_SS_MASTER_MODE_Pos) ///< SPI Slave Select when Master: Hardware monitored Input
#define ARM_SPI_SS_SLAVE_MODE_Pos 21
#define ARM_SPI_SS_SLAVE_MODE_Msk (1UL << ARM_SPI_SS_SLAVE_MODE_Pos)
#define ARM_SPI_SS_SLAVE_HW (0UL << ARM_SPI_SS_SLAVE_MODE_Pos) ///< SPI Slave Select when Slave: Hardware monitored (default)
#define ARM_SPI_SS_SLAVE_SW (1UL << ARM_SPI_SS_SLAVE_MODE_Pos) ///< SPI Slave Select when Slave: Software controlled
/*----- SPI Control Codes: Miscellaneous Controls -----*/
#define ARM_SPI_SET_BUS_SPEED (0x10UL << ARM_SPI_CONTROL_Pos) ///< Set Bus Speed in bps; arg = value
#define ARM_SPI_GET_BUS_SPEED (0x11UL << ARM_SPI_CONTROL_Pos) ///< Get Bus Speed in bps
#define ARM_SPI_SET_DEFAULT_TX_VALUE (0x12UL << ARM_SPI_CONTROL_Pos) ///< Set default Transmit value; arg = value
#define ARM_SPI_CONTROL_SS (0x13UL << ARM_SPI_CONTROL_Pos) ///< Control Slave Select; arg: 0=inactive, 1=active
#define ARM_SPI_ABORT_TRANSFER (0x14UL << ARM_SPI_CONTROL_Pos) ///< Abort current data transfer
/****** SPI Slave Select Signal definitions *****/
#define ARM_SPI_SS_INACTIVE 0 ///< SPI Slave Select Signal Inactive
#define ARM_SPI_SS_ACTIVE 1 ///< SPI Slave Select Signal Active
/****** SPI specific error codes *****/
#define ARM_SPI_ERROR_MODE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Specified Mode not supported
#define ARM_SPI_ERROR_FRAME_FORMAT (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Specified Frame Format not supported
#define ARM_SPI_ERROR_DATA_BITS (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Specified number of Data bits not supported
#define ARM_SPI_ERROR_BIT_ORDER (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Specified Bit order not supported
#define ARM_SPI_ERROR_SS_MODE (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Specified Slave Select Mode not supported
/**
\brief SPI Status
*/
typedef volatile struct _ARM_SPI_STATUS {
uint32_t busy : 1; ///< Transmitter/Receiver busy flag
uint32_t data_lost : 1; ///< Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint32_t mode_fault : 1; ///< Mode fault detected; optional (cleared on start of transfer operation)
uint32_t reserved : 29;
} ARM_SPI_STATUS;
/****** SPI Event *****/
#define ARM_SPI_EVENT_TRANSFER_COMPLETE (1UL << 0) ///< Data Transfer completed
#define ARM_SPI_EVENT_DATA_LOST (1UL << 1) ///< Data lost: Receive overflow / Transmit underflow
#define ARM_SPI_EVENT_MODE_FAULT (1UL << 2) ///< Master Mode Fault (SS deactivated when Master)
// Function documentation
/**
\fn ARM_DRIVER_VERSION ARM_SPI_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn ARM_SPI_CAPABILITIES ARM_SPI_GetCapabilities (void)
\brief Get driver capabilities.
\return \ref ARM_SPI_CAPABILITIES
\fn int32_t ARM_SPI_Initialize (ARM_SPI_SignalEvent_t cb_event)
\brief Initialize SPI Interface.
\param[in] cb_event Pointer to \ref ARM_SPI_SignalEvent
\return \ref execution_status
\fn int32_t ARM_SPI_Uninitialize (void)
\brief De-initialize SPI Interface.
\return \ref execution_status
\fn int32_t ARM_SPI_PowerControl (ARM_POWER_STATE state)
\brief Control SPI Interface Power.
\param[in] state Power state
\return \ref execution_status
\fn int32_t ARM_SPI_Send (const void *data, uint32_t num)
\brief Start sending data to SPI transmitter.
\param[in] data Pointer to buffer with data to send to SPI transmitter
\param[in] num Number of data items to send
\return \ref execution_status
\fn int32_t ARM_SPI_Receive (void *data, uint32_t num)
\brief Start receiving data from SPI receiver.
\param[out] data Pointer to buffer for data to receive from SPI receiver
\param[in] num Number of data items to receive
\return \ref execution_status
\fn int32_t ARM_SPI_Transfer (const void *data_out,
void *data_in,
uint32_t num)
\brief Start sending/receiving data to/from SPI transmitter/receiver.
\param[in] data_out Pointer to buffer with data to send to SPI transmitter
\param[out] data_in Pointer to buffer for data to receive from SPI receiver
\param[in] num Number of data items to transfer
\return \ref execution_status
\fn uint32_t ARM_SPI_GetDataCount (void)
\brief Get transferred data count.
\return number of data items transferred
\fn int32_t ARM_SPI_Control (uint32_t control, uint32_t arg)
\brief Control SPI Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\return common \ref execution_status and driver specific \ref spi_execution_status
\fn ARM_SPI_STATUS ARM_SPI_GetStatus (void)
\brief Get SPI status.
\return SPI status \ref ARM_SPI_STATUS
\fn void ARM_SPI_SignalEvent (uint32_t event)
\brief Signal SPI Events.
\param[in] event \ref SPI_events notification mask
\return none
*/
typedef void (*ARM_SPI_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_SPI_SignalEvent : Signal SPI Event.
/**
\brief SPI Driver Capabilities.
*/
typedef struct _ARM_SPI_CAPABILITIES {
uint32_t simplex : 1; ///< supports Simplex Mode (Master and Slave)
uint32_t ti_ssi : 1; ///< supports TI Synchronous Serial Interface
uint32_t microwire : 1; ///< supports Microwire Interface
uint32_t event_mode_fault : 1; ///< Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT
uint32_t reserved : 28; ///< Reserved (must be zero)
} ARM_SPI_CAPABILITIES;
/**
\brief Access structure of the SPI Driver.
*/
typedef struct _ARM_DRIVER_SPI {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_SPI_GetVersion : Get driver version.
ARM_SPI_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref ARM_SPI_GetCapabilities : Get driver capabilities.
int32_t (*Initialize) (ARM_SPI_SignalEvent_t cb_event); ///< Pointer to \ref ARM_SPI_Initialize : Initialize SPI Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_SPI_Uninitialize : De-initialize SPI Interface.
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_SPI_PowerControl : Control SPI Interface Power.
int32_t (*Send) (const void *data, uint32_t num); ///< Pointer to \ref ARM_SPI_Send : Start sending data to SPI Interface.
int32_t (*Receive) ( void *data, uint32_t num); ///< Pointer to \ref ARM_SPI_Receive : Start receiving data from SPI Interface.
int32_t (*Transfer) (const void *data_out,
void *data_in,
uint32_t num); ///< Pointer to \ref ARM_SPI_Transfer : Start sending/receiving data to/from SPI.
uint32_t (*GetDataCount) (void); ///< Pointer to \ref ARM_SPI_GetDataCount : Get transferred data count.
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_SPI_Control : Control SPI Interface.
ARM_SPI_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_SPI_GetStatus : Get SPI status.
} const ARM_DRIVER_SPI;
#ifdef __cplusplus
}
#endif
#endif /* DRIVER_SPI_H_ */

View File

@@ -0,0 +1,358 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Date: 2. Feb 2017
* $Revision: V2.3
*
* Project: USART (Universal Synchronous Asynchronous Receiver Transmitter)
* Driver definitions
*/
/* History:
* Version 2.3
* ARM_USART_STATUS and ARM_USART_MODEM_STATUS made volatile
* Version 2.2
* Corrected ARM_USART_CPOL_Pos and ARM_USART_CPHA_Pos definitions
* Version 2.1
* Removed optional argument parameter from Signal Event
* Version 2.0
* New simplified driver:
* complexity moved to upper layer (especially data handling)
* more unified API for different communication interfaces
* renamed driver UART -> USART (Asynchronous & Synchronous)
* Added modes:
* Synchronous
* Single-wire
* IrDA
* Smart Card
* Changed prefix ARM_DRV -> ARM_DRIVER
* Version 1.10
* Namespace prefix ARM_ added
* Version 1.01
* Added events:
* ARM_UART_EVENT_TX_EMPTY, ARM_UART_EVENT_RX_TIMEOUT
* ARM_UART_EVENT_TX_THRESHOLD, ARM_UART_EVENT_RX_THRESHOLD
* Added functions: SetTxThreshold, SetRxThreshold
* Added "rx_timeout_event" to capabilities
* Version 1.00
* Initial release
*/
#ifndef DRIVER_USART_H_
#define DRIVER_USART_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "Driver_Common.h"
#define ARM_USART_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,3) /* API version */
/****** USART Control Codes *****/
#define ARM_USART_CONTROL_Pos 0
#define ARM_USART_CONTROL_Msk (0xFFUL << ARM_USART_CONTROL_Pos)
/*----- USART Control Codes: Mode -----*/
#define ARM_USART_MODE_ASYNCHRONOUS (0x01UL << ARM_USART_CONTROL_Pos) ///< UART (Asynchronous); arg = Baudrate
#define ARM_USART_MODE_SYNCHRONOUS_MASTER (0x02UL << ARM_USART_CONTROL_Pos) ///< Synchronous Master (generates clock signal); arg = Baudrate
#define ARM_USART_MODE_SYNCHRONOUS_SLAVE (0x03UL << ARM_USART_CONTROL_Pos) ///< Synchronous Slave (external clock signal)
#define ARM_USART_MODE_SINGLE_WIRE (0x04UL << ARM_USART_CONTROL_Pos) ///< UART Single-wire (half-duplex); arg = Baudrate
#define ARM_USART_MODE_IRDA (0x05UL << ARM_USART_CONTROL_Pos) ///< UART IrDA; arg = Baudrate
#define ARM_USART_MODE_SMART_CARD (0x06UL << ARM_USART_CONTROL_Pos) ///< UART Smart Card; arg = Baudrate
/*----- USART Control Codes: Mode Parameters: Data Bits -----*/
#define ARM_USART_DATA_BITS_Pos 8
#define ARM_USART_DATA_BITS_Msk (7UL << ARM_USART_DATA_BITS_Pos)
#define ARM_USART_DATA_BITS_5 (5UL << ARM_USART_DATA_BITS_Pos) ///< 5 Data bits
#define ARM_USART_DATA_BITS_6 (6UL << ARM_USART_DATA_BITS_Pos) ///< 6 Data bit
#define ARM_USART_DATA_BITS_7 (7UL << ARM_USART_DATA_BITS_Pos) ///< 7 Data bits
#define ARM_USART_DATA_BITS_8 (0UL << ARM_USART_DATA_BITS_Pos) ///< 8 Data bits (default)
#define ARM_USART_DATA_BITS_9 (1UL << ARM_USART_DATA_BITS_Pos) ///< 9 Data bits
/*----- USART Control Codes: Mode Parameters: Parity -----*/
#define ARM_USART_PARITY_Pos 12
#define ARM_USART_PARITY_Msk (3UL << ARM_USART_PARITY_Pos)
#define ARM_USART_PARITY_NONE (0UL << ARM_USART_PARITY_Pos) ///< No Parity (default)
#define ARM_USART_PARITY_EVEN (1UL << ARM_USART_PARITY_Pos) ///< Even Parity
#define ARM_USART_PARITY_ODD (2UL << ARM_USART_PARITY_Pos) ///< Odd Parity
/*----- USART Control Codes: Mode Parameters: Stop Bits -----*/
#define ARM_USART_STOP_BITS_Pos 14
#define ARM_USART_STOP_BITS_Msk (3UL << ARM_USART_STOP_BITS_Pos)
#define ARM_USART_STOP_BITS_1 (0UL << ARM_USART_STOP_BITS_Pos) ///< 1 Stop bit (default)
#define ARM_USART_STOP_BITS_2 (1UL << ARM_USART_STOP_BITS_Pos) ///< 2 Stop bits
#define ARM_USART_STOP_BITS_1_5 (2UL << ARM_USART_STOP_BITS_Pos) ///< 1.5 Stop bits
#define ARM_USART_STOP_BITS_0_5 (3UL << ARM_USART_STOP_BITS_Pos) ///< 0.5 Stop bits
/*----- USART Control Codes: Mode Parameters: Flow Control -----*/
#define ARM_USART_FLOW_CONTROL_Pos 16
#define ARM_USART_FLOW_CONTROL_Msk (3UL << ARM_USART_FLOW_CONTROL_Pos)
#define ARM_USART_FLOW_CONTROL_NONE (0UL << ARM_USART_FLOW_CONTROL_Pos) ///< No Flow Control (default)
#define ARM_USART_FLOW_CONTROL_RTS (1UL << ARM_USART_FLOW_CONTROL_Pos) ///< RTS Flow Control
#define ARM_USART_FLOW_CONTROL_CTS (2UL << ARM_USART_FLOW_CONTROL_Pos) ///< CTS Flow Control
#define ARM_USART_FLOW_CONTROL_RTS_CTS (3UL << ARM_USART_FLOW_CONTROL_Pos) ///< RTS/CTS Flow Control
/*----- USART Control Codes: Mode Parameters: Clock Polarity (Synchronous mode) -----*/
#define ARM_USART_CPOL_Pos 18
#define ARM_USART_CPOL_Msk (1UL << ARM_USART_CPOL_Pos)
#define ARM_USART_CPOL0 (0UL << ARM_USART_CPOL_Pos) ///< CPOL = 0 (default)
#define ARM_USART_CPOL1 (1UL << ARM_USART_CPOL_Pos) ///< CPOL = 1
/*----- USART Control Codes: Mode Parameters: Clock Phase (Synchronous mode) -----*/
#define ARM_USART_CPHA_Pos 19
#define ARM_USART_CPHA_Msk (1UL << ARM_USART_CPHA_Pos)
#define ARM_USART_CPHA0 (0UL << ARM_USART_CPHA_Pos) ///< CPHA = 0 (default)
#define ARM_USART_CPHA1 (1UL << ARM_USART_CPHA_Pos) ///< CPHA = 1
/*----- USART Control Codes: Miscellaneous Controls -----*/
#define ARM_USART_SET_DEFAULT_TX_VALUE (0x10UL << ARM_USART_CONTROL_Pos) ///< Set default Transmit value (Synchronous Receive only); arg = value
#define ARM_USART_SET_IRDA_PULSE (0x11UL << ARM_USART_CONTROL_Pos) ///< Set IrDA Pulse in ns; arg: 0=3/16 of bit period
#define ARM_USART_SET_SMART_CARD_GUARD_TIME (0x12UL << ARM_USART_CONTROL_Pos) ///< Set Smart Card Guard Time; arg = number of bit periods
#define ARM_USART_SET_SMART_CARD_CLOCK (0x13UL << ARM_USART_CONTROL_Pos) ///< Set Smart Card Clock in Hz; arg: 0=Clock not generated
#define ARM_USART_CONTROL_SMART_CARD_NACK (0x14UL << ARM_USART_CONTROL_Pos) ///< Smart Card NACK generation; arg: 0=disabled, 1=enabled
#define ARM_USART_CONTROL_TX (0x15UL << ARM_USART_CONTROL_Pos) ///< Transmitter; arg: 0=disabled, 1=enabled
#define ARM_USART_CONTROL_RX (0x16UL << ARM_USART_CONTROL_Pos) ///< Receiver; arg: 0=disabled, 1=enabled
#define ARM_USART_CONTROL_BREAK (0x17UL << ARM_USART_CONTROL_Pos) ///< Continuous Break transmission; arg: 0=disabled, 1=enabled
#define ARM_USART_ABORT_SEND (0x18UL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Send
#define ARM_USART_ABORT_RECEIVE (0x19UL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Receive
#define ARM_USART_ABORT_TRANSFER (0x1AUL << ARM_USART_CONTROL_Pos) ///< Abort \ref ARM_USART_Transfer
#define ARM_USART_CONTROL_FLUSH_TX (0x1BUL << ARM_USART_CONTROL_Pos) ///< FLUSH TX FIFO
#define ARM_USART_CONTROL_PURGE_COMM (0x1CUL << ARM_USART_CONTROL_Pos) ///< Purge communition(clear rx & tx fifo)
/****** USART specific error codes *****/
#define ARM_USART_ERROR_MODE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Specified Mode not supported
#define ARM_USART_ERROR_BAUDRATE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Specified baudrate not supported
#define ARM_USART_ERROR_DATA_BITS (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Specified number of Data bits not supported
#define ARM_USART_ERROR_PARITY (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Specified Parity not supported
#define ARM_USART_ERROR_STOP_BITS (ARM_DRIVER_ERROR_SPECIFIC - 5) ///< Specified number of Stop bits not supported
#define ARM_USART_ERROR_FLOW_CONTROL (ARM_DRIVER_ERROR_SPECIFIC - 6) ///< Specified Flow Control not supported
#define ARM_USART_ERROR_CPOL (ARM_DRIVER_ERROR_SPECIFIC - 7) ///< Specified Clock Polarity not supported
#define ARM_USART_ERROR_CPHA (ARM_DRIVER_ERROR_SPECIFIC - 8) ///< Specified Clock Phase not supported
/**
\brief USART Status
*/
typedef volatile struct _ARM_USART_STATUS {
uint32_t tx_busy : 1; ///< Transmitter busy flag
uint32_t rx_busy : 1; ///< Receiver busy flag
uint32_t tx_underflow : 1; ///< Transmit data underflow detected (cleared on start of next send operation)
uint32_t rx_overflow : 1; ///< Receive data overflow detected (cleared on start of next receive operation)
uint32_t rx_break : 1; ///< Break detected on receive (cleared on start of next receive operation)
uint32_t rx_framing_error : 1; ///< Framing error detected on receive (cleared on start of next receive operation)
uint32_t rx_parity_error : 1; ///< Parity error detected on receive (cleared on start of next receive operation)
uint32_t is_send_block : 1; ///< Whether Send API works in blocking way
uint32_t reserved : 24;
} ARM_USART_STATUS;
/**
\brief USART Modem Control
*/
typedef enum _ARM_USART_MODEM_CONTROL {
ARM_USART_RTS_CLEAR, ///< Deactivate RTS
ARM_USART_RTS_SET, ///< Activate RTS
ARM_USART_DTR_CLEAR, ///< Deactivate DTR
ARM_USART_DTR_SET ///< Activate DTR
} ARM_USART_MODEM_CONTROL;
/**
\brief USART Modem Status
*/
typedef volatile struct _ARM_USART_MODEM_STATUS {
uint32_t cts : 1; ///< CTS state: 1=Active, 0=Inactive
uint32_t dsr : 1; ///< DSR state: 1=Active, 0=Inactive
uint32_t dcd : 1; ///< DCD state: 1=Active, 0=Inactive
uint32_t ri : 1; ///< RI state: 1=Active, 0=Inactive
uint32_t reserved : 28;
} ARM_USART_MODEM_STATUS;
/****** USART Event *****/
#define ARM_USART_EVENT_SEND_COMPLETE (1UL << 0) ///< Send completed; however USART may still transmit data
#define ARM_USART_EVENT_RECEIVE_COMPLETE (1UL << 1) ///< Receive completed
#define ARM_USART_EVENT_TRANSFER_COMPLETE (1UL << 2) ///< Transfer completed
#define ARM_USART_EVENT_TX_COMPLETE (1UL << 3) ///< Transmit completed (optional)
#define ARM_USART_EVENT_TX_UNDERFLOW (1UL << 4) ///< Transmit data not available (Synchronous Slave)
#define ARM_USART_EVENT_RX_OVERFLOW (1UL << 5) ///< Receive data overflow
#define ARM_USART_EVENT_RX_TIMEOUT (1UL << 6) ///< Receive character timeout (optional)
#define ARM_USART_EVENT_RX_BREAK (1UL << 7) ///< Break detected on receive
#define ARM_USART_EVENT_RX_FRAMING_ERROR (1UL << 8) ///< Framing error detected on receive
#define ARM_USART_EVENT_RX_PARITY_ERROR (1UL << 9) ///< Parity error detected on receive
#define ARM_USART_EVENT_CTS (1UL << 10) ///< CTS state changed (optional)
#define ARM_USART_EVENT_DSR (1UL << 11) ///< DSR state changed (optional)
#define ARM_USART_EVENT_DCD (1UL << 12) ///< DCD state changed (optional)
#define ARM_USART_EVENT_RI (1UL << 13) ///< RI state changed (optional)
#define ARM_USART_EVENT_AUTO_BAUDRATE_DONE (1UL << 14) ///< Auto baudrate dection completed
// Function documentation
/**
\fn ARM_DRIVER_VERSION ARM_USART_GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
\fn ARM_USART_CAPABILITIES ARM_USART_GetCapabilities (void)
\brief Get driver capabilities
\return \ref ARM_USART_CAPABILITIES
\fn int32_t ARM_USART_Initialize (ARM_USART_SignalEvent_t cb_event)
\brief Initialize USART Interface.
\param[in] cb_event Pointer to \ref ARM_USART_SignalEvent
\return \ref execution_status
\fn int32_t ARM_USART_Uninitialize (void)
\brief De-initialize USART Interface.
\return \ref execution_status
\fn int32_t ARM_USART_PowerControl (ARM_POWER_STATE state)
\brief Control USART Interface Power.
\param[in] state Power state
\return \ref execution_status
\fn int32_t ARM_USART_Send (const void *data, uint32_t num)
\brief Start sending data to USART transmitter.
\param[in] data Pointer to buffer with data to send to USART transmitter
\param[in] num Number of data items to send
\return \ref execution_status
\fn int32_t ARM_USART_Receive (void *data, uint32_t num)
\brief Start receiving data from USART receiver.
\param[out] data Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to receive
\return \ref execution_status
\fn int32_t ARM_USART_Transfer (const void *data_out,
void *data_in,
uint32_t num)
\brief Start sending/receiving data to/from USART transmitter/receiver.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return \ref execution_status
\fn uint32_t ARM_USART_GetTxCount (void)
\brief Get transmitted data count.
\return number of data items transmitted
\fn uint32_t ARM_USART_GetRxCount (void)
\brief Get received data count.
\return number of data items received
\fn int32_t ARM_USART_Control (uint32_t control, uint32_t arg)
\brief Control USART Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\return common \ref execution_status and driver specific \ref usart_execution_status
\fn ARM_USART_STATUS ARM_USART_GetStatus (void)
\brief Get USART status.
\return USART status \ref ARM_USART_STATUS
\fn int32_t ARM_USART_SetModemControl (ARM_USART_MODEM_CONTROL control)
\brief Set USART Modem Control line state.
\param[in] control \ref ARM_USART_MODEM_CONTROL
\return \ref execution_status
\fn ARM_USART_MODEM_STATUS ARM_USART_GetModemStatus (void)
\brief Get USART Modem Status lines state.
\return modem status \ref ARM_USART_MODEM_STATUS
\fn uint32_t ARM_USART_GetBaudRate (void)
\brief Get current baud rate.
\return current baud rate
\fn void ARM_USART_SignalEvent (uint32_t event)
\brief Signal USART Events.
\param[in] event \ref USART_events notification mask
\return none
\fn int32_t ARM_USART_SendPolling (const void *data, uint32_t num)
\brief Start sending data to USART transmitter in polling way.
\param[in] data Pointer to buffer with data to send to USART transmitter
\param[in] num Number of data items to send
\return \ref execution_status
*/
typedef void (*ARM_USART_SignalEvent_t) (uint32_t event); ///< Pointer to \ref ARM_USART_SignalEvent : Signal USART Event.
/**
\brief USART Device Driver Capabilities.
*/
typedef struct _ARM_USART_CAPABILITIES {
uint32_t asynchronous : 1; ///< supports UART (Asynchronous) mode
uint32_t synchronous_master : 1; ///< supports Synchronous Master mode
uint32_t synchronous_slave : 1; ///< supports Synchronous Slave mode
uint32_t single_wire : 1; ///< supports UART Single-wire mode
uint32_t irda : 1; ///< supports UART IrDA mode
uint32_t smart_card : 1; ///< supports UART Smart Card mode
uint32_t smart_card_clock : 1; ///< Smart Card Clock generator available
uint32_t flow_control_rts : 1; ///< RTS Flow Control available
uint32_t flow_control_cts : 1; ///< CTS Flow Control available
uint32_t event_tx_complete : 1; ///< Transmit completed event: \ref ARM_USART_EVENT_TX_COMPLETE
uint32_t event_rx_timeout : 1; ///< Signal receive character timeout event: \ref ARM_USART_EVENT_RX_TIMEOUT
uint32_t rts : 1; ///< RTS Line: 0=not available, 1=available
uint32_t cts : 1; ///< CTS Line: 0=not available, 1=available
uint32_t dtr : 1; ///< DTR Line: 0=not available, 1=available
uint32_t dsr : 1; ///< DSR Line: 0=not available, 1=available
uint32_t dcd : 1; ///< DCD Line: 0=not available, 1=available
uint32_t ri : 1; ///< RI Line: 0=not available, 1=available
uint32_t event_cts : 1; ///< Signal CTS change event: \ref ARM_USART_EVENT_CTS
uint32_t event_dsr : 1; ///< Signal DSR change event: \ref ARM_USART_EVENT_DSR
uint32_t event_dcd : 1; ///< Signal DCD change event: \ref ARM_USART_EVENT_DCD
uint32_t event_ri : 1; ///< Signal RI change event: \ref ARM_USART_EVENT_RI
uint32_t reserved : 11; ///< Reserved (must be zero)
} ARM_USART_CAPABILITIES;
/**
\brief Access structure of the USART Driver.
*/
typedef struct _ARM_DRIVER_USART {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_USART_GetVersion : Get driver version.
ARM_USART_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref ARM_USART_GetCapabilities : Get driver capabilities.
int32_t (*Initialize) (ARM_USART_SignalEvent_t cb_event); ///< Pointer to \ref ARM_USART_Initialize : Initialize USART Interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_USART_Uninitialize : De-initialize USART Interface.
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_USART_PowerControl : Control USART Interface Power.
int32_t (*Send) (const void *data, uint32_t num); ///< Pointer to \ref ARM_USART_Send : Start sending data to USART transmitter.
int32_t (*Receive) ( void *data, uint32_t num); ///< Pointer to \ref ARM_USART_Receive : Start receiving data from USART receiver.
int32_t (*Transfer) (const void *data_out,
void *data_in,
uint32_t num); ///< Pointer to \ref ARM_USART_Transfer : Start sending/receiving data to/from USART.
uint32_t (*GetTxCount) (void); ///< Pointer to \ref ARM_USART_GetTxCount : Get transmitted data count.
uint32_t (*GetRxCount) (void); ///< Pointer to \ref ARM_USART_GetRxCount : Get received data count.
int32_t (*Control) (uint32_t control, uint32_t arg); ///< Pointer to \ref ARM_USART_Control : Control USART Interface.
ARM_USART_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_USART_GetStatus : Get USART status.
int32_t (*SetModemControl) (ARM_USART_MODEM_CONTROL control); ///< Pointer to \ref ARM_USART_SetModemControl : Set USART Modem Control line state.
ARM_USART_MODEM_STATUS (*GetModemStatus) (void); ///< Pointer to \ref ARM_USART_GetModemStatus : Get USART Modem Status lines state.
uint32_t (*GetBaudRate) (void); ///< Pointer to \ref ARM_USART_GetBaudRate : Get current baud rate.
int32_t (*SendPolling) (const void *data, uint32_t num); ///< Pointer to \ref ARM_USART_SendPolling : Start sending data to USART transmitter in polling way. <b> This is an extended API not inlcuded in original CMSIS driver version.</b>
} const ARM_DRIVER_USART;
#ifdef __cplusplus
}
#endif
#endif /* DRIVER_USART_H_ */

View File

@@ -0,0 +1,93 @@
#ifndef BSP_I2C_H
#define BSP_I2C_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
// I2C Driver state flags
#define I2C_FLAG_INIT BIT(0) // Driver initialized
#define I2C_FLAG_POWER BIT(1) // Driver power on
#define I2C_FLAG_SETUP BIT(2) // Master configured, clock set
#define I2C_FLAG_MASTER_TX BIT(3) // Master tx
#define I2C_FLAG_MASTER_RX BIT(4) // Master rx
#define I2C_FLAG_SLAVE_TX BIT(5) // Slave tx
#define I2C_FLAG_SLAVE_RX BIT(6) // Slave rx
#define I2C_NO_STARTSTOP (0x00000000U)
#define I2C_GENERATE_STOP (I2C_SCR_STOP_Msk)
#define I2C_GENERATE_START_READ (I2C_SCR_START_Msk | I2C_SCR_TARGET_RWN_Msk)
#define I2C_GENERATE_START_WRITE (I2C_SCR_START_Msk)
#define I2C_GENERATE_RESTART_READ (I2C_SCR_RESTART_Msk | I2C_SCR_TARGET_RWN_Msk)
#define I2C_GENERATE_RESTART_WRITE (I2C_SCR_RESTART_Msk)
#define I2C_MEMADD_SIZE_8BIT (0x00000001U)
#define I2C_MEMADD_SIZE_16BIT (0x00000002U)
#define I2C_AUTOMATIC_MODE1 (0x01) // byte_num_unknown = 0
#define I2C_AUTOMATIC_MODE2 (0x02) // byte_num_unknown = 1
#define I2C_DEDICATED_MODE (0x03)
// I2C IRQ
typedef const struct _I2C_IRQ {
IRQn_Type irq_num; // I2C IRQ Number
IRQ_Callback_t cb_irq;
} I2C_IRQ;
// I2C PINS
typedef const struct _I2C_PIN {
PIN *pin_scl; // SCL Pin identifier
PIN *pin_sda; // SDA Pin identifier
} I2C_PINS;
// I2C DMA
typedef struct _I2C_DMA {
DmaInstance_e tx_instance; // Transmit DMA instance
int8_t tx_ch; // Transmit channel number
uint8_t tx_req; // Transmit DMA request number
void (*tx_callback)(uint32_t event); // Transmit callback
DmaInstance_e rx_instance; // Receive DMA instance
int8_t rx_ch; // Receive channel number
uint8_t rx_req; // Receive DMA request number
void (*rx_callback)(uint32_t event); // Receive callback
} I2C_DMA;
// I2C Control Information
typedef struct {
ARM_I2C_SignalEvent_t cb_event; // Event callback
ARM_I2C_STATUS status; // Status flags
uint8_t flags; // Control and state flags
uint8_t sla_rw; // Slave address and RW bit
bool pending; // Transfer pending (no STOP)
uint8_t stalled; // Stall mode status flags
uint8_t con_aa; // I2C slave CON flag
uint32_t cnt; // Master transfer count
uint8_t *data; // Master data to transfer
uint32_t num; // Number of bytes to transfer
uint8_t *sdata; // Slave data to transfer
uint32_t snum; // Number of bytes to transfer
} I2C_CTRL;
// I2C Resources definition
typedef struct {
I2C_TypeDef *reg; // I2C peripheral register interface
I2C_PINS pins; // I2C PINS config
I2C_DMA* dma; // I2C DMA configuration
I2C_IRQ* irq; // I2C IRQ
I2C_CTRL *ctrl; // Run-Time control information
} const I2C_RESOURCES;
#ifdef __cplusplus
}
#endif
#endif /* BSP_I2C_H */

View File

@@ -0,0 +1,116 @@
#ifndef BSP_LPUSART_H
#define BSP_LPUSART_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#include "ec618.h"
#include "bsp.h"
// LPUSART flags
#define LPUSART_FLAG_INITIALIZED (1U << 0) // LPUSARTinitialized
#define LPUSART_FLAG_POWER_FULL (1U << 1) // LPUSART powered FULL
#define LPUSART_FLAG_POWER_LOW (1U << 2) // LPUSART powered LOW
#define LPUSART_FLAG_CONFIGURED (1U << 3) // LPUSART configured
#define LPUSART_FLAG_TX_ENABLED (1U << 4) // LPUSART TX enabled
#define LPUSART_FLAG_RX_ENABLED (1U << 5) // LPUSART RX enabled
#define LPUSART_FLAG_SEND_ACTIVE (1U << 6) // LPUSART send active
#define LPUSART_FLAG_POWER_MSK (LPUSART_FLAG_POWER_LOW | LPUSART_FLAG_POWER_FULL)
// LPUSART IRQ
typedef const struct _LPUSART_IRQ {
IRQn_Type irq_num; // LPUSART IRQ Number
IRQ_Callback_t cb_irq;
} LPUSART_IRQ;
// LPUSART TX DMA
typedef struct _LPUSART_TX_DMA {
DmaInstance_e instance; // DMA instance
int8_t channel; // Channel number
uint8_t request; // DMA request number
void (*callback)(uint32_t event); // Tx callback
} LPUSART_TX_DMA;
// LPUSART RX DMA
typedef struct _LPUSART_RX_DMA {
DmaInstance_e instance; // DMA instance
int8_t channel; // Channel number
uint8_t request; // DMA request number
DmaDescriptor_t *descriptor; // Rx descriptor
void (*callback)(uint32_t event); // Rx callback
} LPUSART_RX_DMA;
// LPUSART PINS
typedef const struct _LPUSART_PIN {
const PIN *pin_tx; // TX Pin identifier
const PIN *pin_rx; // RX Pin identifier
const PIN *pin_cts; // CTS Pin identifier
const PIN *pin_rts; // RTS Pin identifier
} LPUSART_PINS;
typedef struct _LPUSART_TRANSFER_INFO {
uint32_t rx_num; // Total number of receive data
uint32_t tx_num; // Total number of transmit data
uint8_t *rx_buf; // Pointer to in data buffer
uint8_t *tx_buf; // Pointer to out data buffer
uint32_t rx_cnt; // Number of data received
uint32_t tx_cnt; // Number of data sent
uint16_t tx_def_val; // Default transmit value
uint16_t rx_dump_val; // Receive dump value
uint8_t send_active; // Send active flag
uint32_t sync_mode; // Synchronous mode flag
} LPUSART_TRANSFER_INFO;
typedef struct _LPUSART_STATUS {
uint8_t rx_busy; // Receiver busy flag
uint8_t rx_dma_triggered; // Receive DMA transfer triggered (cleared on start of next receive operation)
uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation)
uint8_t aon_rx_overflow; // AON FIFO receive data overflow detected (cleared on start of next receive operation)
uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation)
uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation)
uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation)
} LPUSART_STATUS;
typedef struct _LPUSART_INFO {
ARM_USART_SignalEvent_t cb_event; // Event Callback
LPUSART_STATUS rx_status; // Recieve Status flags
LPUSART_TRANSFER_INFO xfer; // LPUSART transfer information
uint8_t flags; // Current LPUSART flags
uint32_t frame_code; // Current LPUSART frame setting code
uint32_t baudrate; // Baudrate
} LPUSART_INFO;
// LPUSART Resources definition
typedef const struct {
USART_TypeDef *co_usart_regs; // LPUSART cooperating uart registers pointer
LPUSARTAON_TypeDef *aon_regs; // LPUSART AON part registers pointer
LPUSARTCORE_TypeDef *core_regs; // LPUSART CORE part registers pointer
LPUSART_PINS pins; // LPUSART PINS config
LPUSART_RX_DMA *dma_rx; // LPUSART DMA register interface
LPUSART_TX_DMA *co_usart_dma_tx; // LPUSART DMA register interface
LPUSART_RX_DMA *co_usart_dma_rx; // LPUSART DMA register interface
LPUSART_IRQ *irq; // LPUSART IRQ
LPUSART_IRQ *co_usart_irq; // LPUSART cooperating uart IRQ
LPUSART_INFO *info; // Run-Time Information
} LPUSART_RESOURCES;
void LPUSART_ClearStopFlag(void);
void LPUSART_SetStopFlag(void);
/*
* Check whether rx is ongoing, return true if rx is ongoing at this moment, otherwise false
*/
bool LPUSART_IsRxActive(void);
#ifdef __cplusplus
}
#endif
#endif /* BSP_LPLPUSART_H */

View File

@@ -0,0 +1,89 @@
#ifndef BSP_SPI_H
#define BSP_SPI_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
// SPI flags
#define SPI_FLAG_INITIALIZED (1UL << 0) // SPI initialized
#define SPI_FLAG_POWERED (1UL << 1) // SPI powered on
#define SPI_FLAG_CONFIGURED (1UL << 2) // SPI configured
#define SPI_FLAG_DATA_LOST (1UL << 3) // SPI data lost occurred
#define SPI_FLAG_MODE_FAULT (1UL << 4) // SPI mode fault occurred
// SPI IRQ
typedef const struct _SPI_IRQ {
IRQn_Type irq_num; // SPI IRQ Number
IRQ_Callback_t cb_irq;
} SPI_IRQ;
// SPI DMA
typedef struct _SPI_DMA {
DmaInstance_e tx_instance; // Transmit DMA instance number
int8_t tx_ch; // Transmit channel number
uint8_t tx_req; // Transmit DMA request number
void (*tx_callback)(uint32_t event); // Transmit callback
DmaInstance_e rx_instance; // Receive DMA instance number
int8_t rx_ch; // Receive channel number
uint8_t rx_req; // Receive DMA request number
void (*rx_callback)(uint32_t event); // Receive callback
} SPI_DMA;
// SPI PINS
typedef const struct _SPI_PIN {
const PIN *pin_sclk; // SCLK Pin identifier
const PIN *pin_ssn; // SSn Pin identifier
const PIN *pin_mosi; // MOSI Pin identifier
const PIN *pin_miso; // MISO Pin identifier
} SPI_PINS;
typedef struct _SPI_STATUS {
uint8_t busy; // Transmitter/Receiver busy flag
uint8_t data_lost; // Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint8_t mode_fault; // Mode fault detected; optional (cleared on start of transfer operation)
} SPI_STATUS;
// SPI Transfer Information (Run-Time)
typedef struct _SPI_TRANSFER_INFO {
uint32_t num; // Total number of transfers
uint8_t *rx_buf; // Pointer to in data buffer
uint8_t *tx_buf; // Pointer to out data buffer
uint32_t rx_cnt; // Number of data received
uint32_t tx_cnt; // Number of data sent
uint32_t dump_val; // Variable for dumping DMA data
uint16_t def_val; // Default transfer value
} SPI_TRANSFER_INFO;
// SPI information (Run-time)
typedef struct _SPI_INFO {
ARM_SPI_SignalEvent_t cb_event; // event callback
SPI_STATUS status; // SPI status flags
SPI_TRANSFER_INFO xfer; // SPI transfer information
uint8_t flags; // SPI driver flags
uint32_t mode; // SPI mode
uint32_t bus_speed; // SPI bus speed
uint8_t data_width; // SPI data bits select in unit of byte
} SPI_INFO;
// SPI Resources definition
typedef struct {
SPI_TypeDef *reg; // SPI register pointer
SPI_PINS pins; // SPI PINS configuration
SPI_DMA *dma; // SPI DMA configuration pointer
SPI_IRQ *irq; // SPI IRQ configuration pointer
SPI_INFO *info; // Run-Time Information
} SPI_RESOURCES;
#ifdef __cplusplus
}
#endif
#endif /* BSP_SPI_H */

View File

@@ -0,0 +1,108 @@
#ifndef BSP_USART_H
#define BSP_USART_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "ec618.h"
#include "bsp.h"
// USART flags
#define USART_FLAG_INITIALIZED (1U << 0) // USARTinitialized
#define USART_FLAG_POWERED (1U << 1) // USART powered on
#define USART_FLAG_CONFIGURED (1U << 2) // USART configured
#define USART_FLAG_TX_ENABLED (1U << 3) // USART TX enabled
#define USART_FLAG_RX_ENABLED (1U << 4) // USART RX enabled
#define USART_FLAG_SEND_ACTIVE (1U << 5) // USART send active
#define USART_TFE_INT (0x2<<USART_IIR_INT_ID_Pos)
#define USART_RDA_INT (0x4<<USART_IIR_INT_ID_Pos)
#define USART_RLS_INT (0x6<<USART_IIR_INT_ID_Pos)
#define USART_CTI_INT (0xC<<USART_IIR_INT_ID_Pos)
#define USART_INT_TYPE_MSK (0xF<<USART_IIR_INT_ID_Pos)
// USART IRQ
typedef const struct _USART_IRQ {
IRQn_Type irq_num; // USART IRQ Number
IRQ_Callback_t cb_irq;
} USART_IRQ;
// USART TX DMA
typedef struct _USART_TX_DMA {
DmaInstance_e instance; // DMA instance
int8_t channel; // Channel number
uint8_t request; // DMA request number
void (*callback)(uint32_t event); // Tx callback
} USART_TX_DMA;
// USART RX DMA
typedef struct _USART_RX_DMA {
DmaInstance_e instance; // DMA instance
int8_t channel; // Channel number
uint8_t request; // DMA request number
DmaDescriptor_t *descriptor; // Rx descriptor
void (*callback)(uint32_t event); // Rx callback
} USART_RX_DMA;
// USART PINS
typedef const struct _USART_PIN {
const PIN *pin_tx; // TX Pin identifier
const PIN *pin_rx; // RX Pin identifier
const PIN *pin_cts; // CTS Pin identifier
const PIN *pin_rts; // RTS Pin identifier
} USART_PINS;
typedef struct _USART_TRANSFER_INFO {
uint32_t rx_num; // Total number of receive data
uint32_t tx_num; // Total number of transmit data
uint8_t *rx_buf; // Pointer to in data buffer
uint8_t *tx_buf; // Pointer to out data buffer
uint32_t rx_cnt; // Number of data received
uint32_t tx_cnt; // Number of data sent
uint16_t tx_def_val; // Default transmit value
uint16_t rx_dump_val; // Receive dump value
uint8_t send_active; // Send active flag
uint32_t sync_mode; // Synchronous mode flag
} USART_TRANSFER_INFO;
typedef struct _USART_STATUS {
uint8_t rx_busy; // Receiver busy flag
uint8_t rx_dma_triggered; // Receive DMA transfer triggered (cleared on start of next receive operation)
uint8_t rx_overflow; // Receive data overflow detected (cleared on start of next receive operation)
uint8_t rx_break; // Break detected on receive (cleared on start of next receive operation)
uint8_t rx_framing_error; // Framing error detected on receive (cleared on start of next receive operation)
uint8_t rx_parity_error; // Parity error detected on receive (cleared on start of next receive operation)
} USART_STATUS;
typedef struct _USART_INFO {
ARM_USART_SignalEvent_t cb_event; // Event Callback
USART_STATUS rx_status; // Recieve Status flags
USART_TRANSFER_INFO xfer; // USART transfer information
uint8_t flags; // Current USART flags
uint32_t frame_code; // Current USART frame setting code
uint32_t baudrate; // Baudrate
} USART_INFO;
// USART Resources definition
typedef const struct {
USART_TypeDef *reg; // USART peripheral pointer
USART_PINS pins; // USART PINS config
USART_TX_DMA *dma_tx; // USART DMA register interface
USART_RX_DMA *dma_rx; // USART DMA register interface
USART_IRQ *usart_irq; // USART IRQ
uint32_t tx_fifo_trig_lvl; // USART TX FIFO trigger level
uint32_t rx_fifo_trig_lvl; // USART RX FIFO trigger level
USART_INFO *info; // Run-Time Information
uint8_t is_unilog_mode; // Act as unilog output
} USART_RESOURCES;
#ifdef __cplusplus
}
#endif
#endif /* BSP_USART_H */

View File

@@ -0,0 +1,463 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: adc.c
* Description: EC618 adc driver source file
* History:
*
****************************************************************************/
#include "adc.h"
#include "ic.h"
#include "slpman.h"
#include "ec618.h"
#include "alarm.h"
#define LDO_AIO_CTRL_REG_ADDR (0x4D020180)
#define ADC_ENABLE() do \
{ \
ADC->CTRL |= ADC_CTRL_LDO_EN_Msk; \
*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR) = 1; \
while((*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR)) == 0); \
} while(0)
#define ADC_DISABLE() do \
{ \
ADC->CTRL &= ~ADC_CTRL_LDO_EN_Msk; \
*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR) = 0; \
while((*(uint32_t*)(LDO_AIO_CTRL_REG_ADDR)) == 1); \
} while(0)
#define ADC_CHANNEL_NUMBER (6)
#ifdef PM_FEATURE_ENABLE
#define LOCK_SLEEP() do \
{ \
slpManDrvVoteSleep(SLP_VOTE_ADC, SLP_ACTIVE_STATE); \
} \
while(0)
#define UNLOCK_SLEEP() do \
{ \
slpManDrvVoteSleep(SLP_VOTE_ADC, SLP_SLP1_STATE); \
} \
while(0)
#endif
#define ADC_DEFAULT_CLOCK_DIVIDER (ADC_CLOCK_DIV_8)
#define ADC_CHANNEL_ENABLE_BIT_POSITION (ADC_AIOCFG_THM_EN_Pos)
/**
\brief size of ADC request queue, value shall be integer power of 2 for fast calcualtion of MOD.
\note The valid number of requests is (this_macro_value - 1)
*/
#define ADC_REQUEST_QUEUE_SIZE (8)
#define ADC_REQUEST_QUEUE_SIZE_MASK (ADC_REQUEST_QUEUE_SIZE - 1)
/**
\brief ADC conversion request queue typedef
*/
typedef struct
{
uint32_t requestArray[ADC_REQUEST_QUEUE_SIZE];
uint32_t head;
uint32_t tail;
} AdcReqeustQueue_t;
static AdcReqeustQueue_t gAdcRequestqueue;
/**
\brief variable for keeping track the index of current request bitmap, see below bitmap layout
*/
static volatile uint32_t gCurrentRequestIndex;
/** \brief Internal used data structure */
typedef struct
{
struct
{
uint32_t AIOCFG; /**< AIO configuration Register */
uint32_t CFG; /**< ADC configuration Register */
} configRegisters;
adcCallback_t eventCallback; /**< Callback function passed in by application */
} AdcChannelDatabase_t;
/**
****************************** Bitmap layout *****************************
*
* 18 17 15 14 12 11 9 8 6 5 3 2 0
*+-----------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*| VREF OUT | CH AIO1 | CH AIO2 | CH AIO3 | CH AIO4 | CH Vbat | CH thermal|
*+-----------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* / \
* / \
* / \
* |APP | PLAT | PHY|
*/
#define CHANNEL_ID_TO_INDEX(channel, userID) ((userID & 0x3U) + (channel & 0x7U) * 3U)
#define ADC_MAX_LOGIC_CHANNELS (ADC_CHANNEL_NUMBER * ADC_USER_MAX)
/** \brief Internal used data structure */
typedef struct
{
uint32_t channelConfigValidBitMap; /**< Bitmap of channel configuration valid flag */
AdcChannelDatabase_t channelDataBase[ADC_MAX_LOGIC_CHANNELS]; /**< Array of channel database, each element represents one configuration */
} AdcDatabase_t;
static AdcDatabase_t g_adcDataBase = {0};
void delay_us(uint32_t us);
static void ADC_requestQueueInit(void)
{
gAdcRequestqueue.head = 0;
gAdcRequestqueue.tail = 0;
gCurrentRequestIndex = ADC_MAX_LOGIC_CHANNELS;
}
// no need to perform atomic access since this function is called only in ISR
static int32_t ADC_requestQueueRead(uint32_t *request)
{
if(gAdcRequestqueue.tail == gAdcRequestqueue.head)
{
// queue is empty
return -1;
}
*request = gAdcRequestqueue.requestArray[gAdcRequestqueue.head];
gAdcRequestqueue.head = (gAdcRequestqueue.head + 1) & ADC_REQUEST_QUEUE_SIZE_MASK;
return 0;
}
static int32_t ADC_requestQueueWrite(uint32_t *request)
{
uint32_t mask;
mask = SaveAndSetIRQMask();
if(((gAdcRequestqueue.tail + 1) & ADC_REQUEST_QUEUE_SIZE_MASK) == gAdcRequestqueue.head)
{
// queue is full
RestoreIRQMask(mask);
return -1;
}
gAdcRequestqueue.requestArray[gAdcRequestqueue.tail] = *request;
gAdcRequestqueue.tail = (gAdcRequestqueue.tail + 1) & ADC_REQUEST_QUEUE_SIZE_MASK;
RestoreIRQMask(mask);
return 0;
}
static void ADC_loadConfigAndStartConversion(uint32_t requestIndex)
{
uint32_t aiocfg;
// clear status first
// LDO has been enabled during initialization phase, here we shall keep this bit set
ADC->CTRL = ADC_CTRL_LDO_EN_Msk | ADC_CTRL_EN_Msk;
// Protect VREF2AIO1 control bit, take care not to overwrite!!!
aiocfg = (ADC->AIOCFG & ADC_AIOCFG_VREF2AIO1_EN_Msk) | g_adcDataBase.channelDataBase[requestIndex].configRegisters.AIOCFG;
#ifdef PM_FEATURE_ENABLE
// thermmal comparator close when sample thm channel
if(aiocfg & ADC_AIOCFG_THM_EN_Msk)
{
alarmThmDisableInAdc();
}
#endif
// Protect VREF2AIO1 control bit, take care not to overwrite!!!
ADC->AIOCFG = aiocfg;
ADC->CFG = g_adcDataBase.channelDataBase[requestIndex].configRegisters.CFG;
#ifdef PM_FEATURE_ENABLE
// thermal channel closed
if((ADC->AIOCFG & ADC_AIOCFG_THM_EN_Msk) == 0)
{
if(alarmThmEnableInAdc() == false)
{
delay_us(10);
}
}
else
#endif
delay_us(10);
// start conversion
ADC->CTRL = (ADC_CTRL_LDO_EN_Msk | ADC_CTRL_EN_Msk | ADC_CTRL_RSTN_Msk);
}
static void ADC_interruptHandler(void)
{
uint32_t requestIndex;
int32_t ret;
ADC->AIOCFG &= ~(ADC_AIOCFG_THM_EN_Msk | ADC_AIOCFG_BATSENS_EN_Msk | ADC_AIOCFG_AIO4_EN_Msk |
ADC_AIOCFG_AIO3_EN_Msk | ADC_AIOCFG_AIO2_EN_Msk | ADC_AIOCFG_AIO1_EN_Msk |
ADC_AIOCFG_AIO4_NO_DIVR_EN_Msk | ADC_AIOCFG_AIO3_NO_DIVR_EN_Msk |
ADC_AIOCFG_AIO2_NO_DIVR_EN_Msk | ADC_AIOCFG_AIO1_NO_DIVR_EN_Msk);
if(g_adcDataBase.channelDataBase[gCurrentRequestIndex].eventCallback != NULL)
{
g_adcDataBase.channelDataBase[gCurrentRequestIndex].eventCallback(ADC->RESULT);
}
// Shall check config validation here since config could be changed in user callback(Deinit is called)
/*
R1 R2 R1 (3 request at once) R1 deInit R2 deInit (validBitMap change to 0 and ADC is disabled)
APP ------------------------------------\ /--------------\ /------------\
| | | | x
v | v | x
--------- --------- xxxxxxxxxxxxxxxxxxxxxxxxxxxx
ADC ISR R1 R2 R1 is still in queue, stuck here(interrupt never occurs)
*/
if(g_adcDataBase.channelConfigValidBitMap != 0)
{
ret = ADC_requestQueueRead(&requestIndex);
// Start next round conversion
if(ret == 0)
{
// there is pending request
gCurrentRequestIndex = requestIndex;
ADC_loadConfigAndStartConversion(gCurrentRequestIndex);
}
else
{
gCurrentRequestIndex = ADC_MAX_LOGIC_CHANNELS;
#ifdef PM_FEATURE_ENABLE
alarmThmEnableInAdc();
UNLOCK_SLEEP();
#endif
}
}
else
{
ADC_requestQueueInit();
#ifdef PM_FEATURE_ENABLE
alarmThmEnableInAdc();
UNLOCK_SLEEP();
#endif
}
}
void ADC_getDefaultConfig(AdcConfig_t *config)
{
ASSERT(config);
config->clockDivider = ADC_DEFAULT_CLOCK_DIVIDER;
config->channelConfig.aioResDiv = ADC_AIO_RESDIV_BYPASS;
}
int32_t ADC_channelInit(AdcChannel_e channel, AdcUser_t userID, const AdcConfig_t *config, adcCallback_t callback)
{
uint32_t mask, configValue, requestIndex;
configValue = 0;
requestIndex = CHANNEL_ID_TO_INDEX(channel, userID);
if(requestIndex >= ADC_MAX_LOGIC_CHANNELS)
{
return -1;
}
mask = SaveAndSetIRQMask();
// AIO1 conflict check
if((channel == ADC_CHANNEL_AIO1) && ((g_adcDataBase.channelConfigValidBitMap & (1 << ADC_MAX_LOGIC_CHANNELS)) != 0))
{
RestoreIRQMask(mask);
return -2;
}
// First Initialization
if(g_adcDataBase.channelConfigValidBitMap == 0)
{
// enable ADC
ADC_ENABLE();
XIC_SetVector(PXIC1_AUXADC_IRQn, ADC_interruptHandler);
XIC_EnableIRQ(PXIC1_AUXADC_IRQn);
ADC_requestQueueInit();
}
g_adcDataBase.channelConfigValidBitMap |= ( 1 << requestIndex);
RestoreIRQMask(mask);
configValue |= ( EIGEN_VAL2FLD(ADC_CFG_WAIT_CTRL, 1) | \
EIGEN_VAL2FLD(ADC_CFG_OFFSET_CTRL, 5) | \
EIGEN_VAL2FLD(ADC_CFG_SAMPLE_AVG, 0) | \
EIGEN_VAL2FLD(ADC_CFG_CLKIN_DIV, config ? config->clockDivider : ADC_DEFAULT_CLOCK_DIVIDER) | \
EIGEN_VAL2FLD(ADC_CFG_VREF_BS, 1) | \
EIGEN_VAL2FLD(ADC_CFG_VREF_SEL, 4) | \
EIGEN_VAL2FLD(ADC_CFG_LDO_SEL, 4) | \
EIGEN_VAL2FLD(ADC_CFG_IBIAS_SEL, 1)
);
g_adcDataBase.channelDataBase[requestIndex].configRegisters.CFG = configValue;
configValue = 0;
switch(channel)
{
case ADC_CHANNEL_THERMAL:
configValue = 1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION) | EIGEN_VAL2FLD(ADC_AIOCFG_THM_SEL, 2);
break;
case ADC_CHANNEL_VBAT:
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | EIGEN_VAL2FLD(ADC_AIOCFG_VBATSEN_RDIV, config->channelConfig.vbatResDiv);
break;
case ADC_CHANNEL_AIO1:
case ADC_CHANNEL_AIO2:
case ADC_CHANNEL_AIO3:
case ADC_CHANNEL_AIO4:
if(config->channelConfig.aioResDiv == ADC_AIO_RESDIV_BYPASS)
{
configValue = 1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION + 4);
}
else if(config->channelConfig.aioResDiv < ADC_AIO_RESDIV_RATIO_8OVER16)
{
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | ADC_AIOCFG_RDIV_BYP_Msk | EIGEN_VAL2FLD(ADC_AIOCFG_RDIV, config->channelConfig.aioResDiv);
}
else
{
configValue = (1 << (channel + ADC_CHANNEL_ENABLE_BIT_POSITION)) | (EIGEN_VAL2FLD(ADC_AIOCFG_RDIV, (config->channelConfig.aioResDiv - ADC_AIO_RESDIV_RATIO_8OVER16)));
}
break;
default:
break;
}
g_adcDataBase.channelDataBase[requestIndex].configRegisters.AIOCFG = configValue;
g_adcDataBase.channelDataBase[requestIndex].eventCallback = callback;
return 0;
}
void ADC_channelDeInit(AdcChannel_e channel, AdcUser_t userID)
{
uint32_t mask = SaveAndSetIRQMask();
g_adcDataBase.channelConfigValidBitMap &= ~(1 << CHANNEL_ID_TO_INDEX(channel, userID));
if(g_adcDataBase.channelConfigValidBitMap == 0)
{
// diable ADC
ADC->CTRL = ADC->CTRL & ADC_CTRL_LDO_EN_Msk;
// disable clock
ADC_DISABLE();
XIC_DisableIRQ(PXIC1_AUXADC_IRQn);
}
RestoreIRQMask(mask);
}
int32_t ADC_startConversion(AdcChannel_e channel, AdcUser_t userID)
{
uint32_t mask, requestIndex;
int32_t ret;
requestIndex = CHANNEL_ID_TO_INDEX(channel, userID);
ASSERT(requestIndex < ADC_MAX_LOGIC_CHANNELS);
mask = SaveAndSetIRQMask();
// validation check
if((g_adcDataBase.channelConfigValidBitMap & (1 << requestIndex)) == 0)
{
RestoreIRQMask(mask);
return -2;
}
// A conversion is ongoing, pending the request
if(gCurrentRequestIndex != ADC_MAX_LOGIC_CHANNELS)
{
RestoreIRQMask(mask);
ret = ADC_requestQueueWrite(&requestIndex);
if(ret != 0)
{
// request queue is full
return ret;
}
}
else
{
gCurrentRequestIndex = requestIndex;
ADC_loadConfigAndStartConversion(gCurrentRequestIndex);
RestoreIRQMask(mask);
#ifdef PM_FEATURE_ENABLE
LOCK_SLEEP();
#endif
}
return 0;
}
int32_t ADC_enableVrefOutput(void)
{
uint32_t mask = SaveAndSetIRQMask();
// AIO1 conflict check
if((g_adcDataBase.channelConfigValidBitMap & (0x7 << (ADC_CHANNEL_AIO1*3U))) != 0)
{
RestoreIRQMask(mask);
return -2;
}
// First Initialization
if(g_adcDataBase.channelConfigValidBitMap == 0)
{
// enable ADC
ADC_ENABLE();
XIC_SetVector(PXIC1_AUXADC_IRQn, ADC_interruptHandler);
XIC_EnableIRQ(PXIC1_AUXADC_IRQn);
ADC_requestQueueInit();
}
ADC->AIOCFG |= ADC_AIOCFG_VREF2AIO1_EN_Msk;
g_adcDataBase.channelConfigValidBitMap |= ( 1 << ADC_MAX_LOGIC_CHANNELS);
RestoreIRQMask(mask);
return 0;
}
void ADC_disableVrefOutput(void)
{
uint32_t mask = SaveAndSetIRQMask();
g_adcDataBase.channelConfigValidBitMap &= ~(1 << ADC_MAX_LOGIC_CHANNELS);
ADC->AIOCFG &= ~ADC_AIOCFG_VREF2AIO1_EN_Msk;
if(g_adcDataBase.channelConfigValidBitMap == 0)
{
// diable ADC
ADC->CTRL = ADC->CTRL & ADC_CTRL_LDO_EN_Msk;
// disable clock
ADC_DISABLE();
XIC_DisableIRQ(PXIC1_AUXADC_IRQn);
}
RestoreIRQMask(mask);
}

View File

@@ -0,0 +1,251 @@
#include "ic.h"
#include "apmu2Peripheral.h"
#ifdef __USER_CODE__
#include "RTE_Device.h"
#else
#include "RTE_Device.h"
#endif
#include "timer.h"
#include "clock.h"
#include DEBUG_LOG_HEADER_FILE
#if (RTE_USB_EN == 1)
void usblpw_enter_start_proc(bool force_cfg_pwr_down);
void usblpw_enter_abort_proc(bool force_cfg_pwr_down);
void usblpw_susp2vbustbl_guard_dlychk(uint32_t cur_tick);
void usblpw_susp2hib_guard_dlychk(uint32_t cur_tick);
void usblpw_retwkup_sleep1_later_recovery(void);
void usblpw_retwkup_sleep1_pre_recovery(void);
#endif
#if (RTE_LPUART_EN == 1)
#include "bsp_lpusart.h"
#endif
// to wakeup in paging wfi for hib timer, should only use in paging.(timer4 can use in app)
#define AP_NEARHIBTIME_INSTANCE (4)
#define AP_NEARHIBTIME_IRQ (PXIC0_TIMER4_IRQn)
#define AP_NEARHIBTIME_MAXIMUM (4294967) // 0xffffffff/1000 ms
// do not use timer5 in app
#define CP_STARTTIME_INSTANCE (5)
#define CP_STARTTIME_IRQ (PXIC0_TIMER5_IRQn)
#define CP_STARTTIME_MAXIMUM (4294967) // 0xffffffff/1000 ms
void apmuPeriUsbEnterStartProc(bool forceCfgPwrDown)
{
#if (RTE_USB_EN == 1)
usblpw_enter_start_proc(forceCfgPwrDown);
#endif
}
void apmuPeriUsbEnterAbortProc(bool forceCfgPwrDown)
{
#if (RTE_USB_EN == 1)
usblpw_enter_abort_proc(forceCfgPwrDown);
#endif
}
void apmuPeriUsbSusp2VbusTblGuardDlyChk(uint32_t cur_tick)
{
#if (RTE_USB_EN == 1)
usblpw_susp2vbustbl_guard_dlychk(cur_tick);
#endif
}
void apmuPeriUsbSusp2HibGuardDlyChk(uint32_t cur_tick)
{
#if (RTE_USB_EN == 1)
usblpw_susp2hib_guard_dlychk(cur_tick);
#endif
}
void apmuPeriUsbSleep1LateRecoverFlow(bool sleepSuccess)
{
#if (RTE_USB_EN == 1)
if(sleepSuccess)
{
usblpw_retwkup_sleep1_later_recovery();
}
#endif
}
void apmuPeriUsbSleep1PreRecoverFlow(bool sleepSuccess)
{
#if (RTE_USB_EN == 1)
if(sleepSuccess)
{
usblpw_retwkup_sleep1_pre_recovery();
}
#endif
}
bool apmuPeriLpuartPreSleepProcess(void)
{
#ifdef __USER_CODE__
extern int soc_uart_sleep_check(uint8_t *result);
uint8_t result;
if (!soc_uart_sleep_check(&result))
{
return result?true:false;
}
#endif
#if (RTE_LPUART_EN == 1)
LPUSART_SetStopFlag();
if(LPUSART_IsRxActive())
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, apmuPeriLpuartPreSleepProcess_1, P_WARNING, "lpuart status, iir: 0x%x, fcsr: 0x%x, tcr: 0x%x, tsr: 0x%x", LPUSART_CORE->IIR, LPUSART_CORE->FCSR, LPUSART_CORE->TCR, LPUSART_CORE->TSR);
LPUSART_ClearStopFlag();
return true;
}
else
{
extern void AonRegSetWakeupEdge(uint8_t index, bool posEnable, bool negEnable);
AonRegSetWakeupEdge(6, false, true);
NVIC_EnableIRQ(LpuartWakeup_IRQn);
}
LPUSART_ClearStopFlag();
return false;
#else
return false;
#endif
}
bool apmuPeriLpuartIsRxActive(void)
{
#ifdef __USER_CODE__
extern int soc_uart_rx_check(uint8_t *result);
uint8_t result;
if (!soc_uart_rx_check(&result))
{
return result?true:false;
}
#endif
#if (RTE_LPUART_EN == 1)
return LPUSART_IsRxActive();
#else
return false;
#endif
}
static void apmuPeriWFITimerExp(void)
{
ECPLAT_PRINTF(UNILOG_PMU, apmu2PeriWFITimerExp_0, P_VALUE, "apmu2PeriWFITimerExp Enter");
if (TIMER_getInterruptFlags(CP_STARTTIME_INSTANCE) & TIMER_MATCH0_INTERRUPT_FLAG)
{
TIMER_clearInterruptFlags(CP_STARTTIME_INSTANCE, TIMER_MATCH0_INTERRUPT_FLAG);
}
TIMER_stop(AP_NEARHIBTIME_INSTANCE);
TIMER_deInit(AP_NEARHIBTIME_INSTANCE);
}
void apmuPeriStartWFITimer(uint32_t ms)
{
int32_t clkRet1,clkRet2;
if(ms<10)
return;
CLOCK_clockReset(FCLK_TIMER4); // to protect setClock error
// TIMER config
// Config TIMER clock, source from 26MHz and divide by 1
clkRet1 = CLOCK_setClockSrc(FCLK_TIMER4, FCLK_TIMER4_SEL_26M);
clkRet2 = CLOCK_setClockDiv(FCLK_TIMER4, 26);
if((clkRet1 != 0) || (clkRet2 != 0))
{
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartWFITimer_0, P_ERROR, "clkRet1=%d, clkRet2=%d, CLKFREQ=0x%x", clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER4));
EC_ASSERT(0, clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER4));
}
TimerConfig_t timerConfig;
TIMER_getDefaultConfig(&timerConfig);
timerConfig.reloadOption = TIMER_RELOAD_ON_MATCH0;
if(ms > AP_NEARHIBTIME_MAXIMUM)
{
ms = AP_NEARHIBTIME_MAXIMUM;
}
timerConfig.match0 = (ms-5)*1000;
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartWFITimer_1, P_VALUE, "apmuPeriStartWFITimer set to %u ms", (ms-5));
TIMER_init(AP_NEARHIBTIME_INSTANCE, &timerConfig);
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH0_SELECT, TIMER_INTERRUPT_LEVEL);
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH1_SELECT, TIMER_INTERRUPT_DISABLED);
TIMER_interruptConfig(AP_NEARHIBTIME_INSTANCE, TIMER_MATCH2_SELECT, TIMER_INTERRUPT_DISABLED);
// Enable TIMER IRQ
XIC_SetVector(AP_NEARHIBTIME_IRQ, apmuPeriWFITimerExp);
XIC_EnableIRQ(AP_NEARHIBTIME_IRQ);
TIMER_start(AP_NEARHIBTIME_INSTANCE);
}
void apmuPeriDeleteWFITimer(void)
{
TIMER_stop(AP_NEARHIBTIME_INSTANCE);
TIMER_deInit(AP_NEARHIBTIME_INSTANCE);
}
void apmuPeriDeleteCPTimer(void)
{
TIMER_stop(CP_STARTTIME_INSTANCE);
TIMER_deInit(CP_STARTTIME_INSTANCE);
}
void apmuPeriClearCPTimerInterrupt(void)
{
if (TIMER_getInterruptFlags(CP_STARTTIME_INSTANCE) & TIMER_MATCH0_INTERRUPT_FLAG)
{
TIMER_clearInterruptFlags(CP_STARTTIME_INSTANCE, TIMER_MATCH0_INTERRUPT_FLAG);
}
}
void apmuPeriStartCPTimer(uint32_t cpStartTime, void* expFunc)
{
int32_t clkRet1,clkRet2;
CLOCK_clockReset(FCLK_TIMER5); // to protect setClock error, can not reproduce easily
// TIMER config
// Config TIMER clock, source from 26MHz and divide by 1
clkRet1 = CLOCK_setClockSrc(FCLK_TIMER5, FCLK_TIMER5_SEL_26M);
clkRet2 = CLOCK_setClockDiv(FCLK_TIMER5, 26);
if((clkRet1 != 0) || (clkRet2 != 0))
{
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartCPTimer_0, P_ERROR, "clkRet1=%d, clkRet2=%d, CLKFREQ=0x%x", clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER5));
EC_ASSERT(0, clkRet1, clkRet2, CLOCK_getClockFreq(FCLK_TIMER5));
}
TimerConfig_t timerConfig;
TIMER_getDefaultConfig(&timerConfig);
timerConfig.reloadOption = TIMER_RELOAD_ON_MATCH0;
if(cpStartTime > CP_STARTTIME_MAXIMUM)
{
cpStartTime = CP_STARTTIME_MAXIMUM;
}
timerConfig.match0 = (cpStartTime-1)*1000;
ECPLAT_PRINTF(UNILOG_PMU, apmuPeriStartCPTimer_1, P_VALUE, "apmuCreateModemStartTimer set to %u ms", (cpStartTime-1));
TIMER_init(CP_STARTTIME_INSTANCE, &timerConfig);
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH0_SELECT, TIMER_INTERRUPT_LEVEL);
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH1_SELECT, TIMER_INTERRUPT_DISABLED);
TIMER_interruptConfig(CP_STARTTIME_INSTANCE, TIMER_MATCH2_SELECT, TIMER_INTERRUPT_DISABLED);
// Enable TIMER IRQ
XIC_SetVector(CP_STARTTIME_IRQ, expFunc);
XIC_EnableIRQ(CP_STARTTIME_IRQ);
TIMER_start(CP_STARTTIME_INSTANCE);
}

View File

@@ -0,0 +1,469 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: clock.c
* Description: EC618 clock driver source file
* History: Rev1.0 2019-02-20
*
****************************************************************************/
#include "clock.h"
#include <assert.h>
#include <string.h>
#include "Driver_Common.h"
#ifdef PM_FEATURE_ENABLE
#include DEBUG_LOG_HEADER_FILE
#endif
extern bool GPR_clockEnableCheck(ClockId_e id);
extern ClockId_e CLOCK_checkClkID(void);
/** \brief support clock driver full feature or not */
#define ENABLE_CLK_TREE_PARENT
/** \brief definition of clk tree element for clock management */
typedef struct _clk_tree_element
{
uint32_t enableCount : 8; /**< counter of each clk has been enabled */
uint32_t parentId : 17; /**< id of this clock's parent clk */
uint32_t hasExtraDependency : 1; /**< whether or not this clock has extra dependent clock */
uint32_t canChangeSrcForcely : 1; /**< whether or not the source of this clock can be changed in enabled state */
} ClkTreeElement_t;
/** \brief clock tree Array */
static ClkTreeElement_t g_clkTreeArray[] =
{
[GET_INDEX_FROM_CLOCK_ID(CLK_CC)] = {1, CLK_MF, 0, 1},
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_MP)] = {1, CLK_MF, 0, 1},
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_XP)] = {1, CLK_MF, 0, 1},
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP)] = {1, INVALID_CLK, 0, 1},
[GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK)] = {1, CLK_32K, 0, 1},
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART0)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART1)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_UART2)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_SPI0)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_SPI1)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2S0)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2S1)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_WDG)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER0)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER1)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER2)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER3)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER4)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_TIMER5)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2C0)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_I2C1)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_USIM0)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_USIM1)] = {0, CLK_MF_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FCLK_KPC)] = {0, CLK_32K_GATED, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_FLASH)] = {1, CLK_MF, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_PSRAM)] = {0, CLK_MF, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_MF)] = {1, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_32K)] = {1, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_HF408M)] = {1, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_HF204M)] = {1, CLK_HF408M, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_HF102M)] = {0, CLK_HF204M, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_HF51M)] = {0, CLK_HF102M, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_32K_GATED)] = {1, CLK_32K, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_MF_GATED)] = {1, CLK_MF, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_MP)] = {1, CLK_CC, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_AP)] = {1, CLK_CC, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_CC_CP)] = {1, CLK_CC, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_AON)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP_MP)] = {0, CLK_SMP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(MFAB_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(AFBBR_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(MSMB_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FLASH_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PSRAM_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ULOG_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(UTFC_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ULDP_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(USBC_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(USBC_PMU_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(USBC_REF_CLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(USBP_REF_CLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(USBC_UTMI_CLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_DAP_AP)] = {1, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_TRACE_AP)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_SYSTICK_AP)] = {0, CLK_SYSTICK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_APB_AP)] = {1, CLK_APB_XP, 1, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_SMP_AP)] = {1, CLK_SMP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CLK_CLKCAL)] = {0, CLK_MF, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_SIPC)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_AON)] = {1, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_CPMU)] = {1, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_PMDIG)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_RFDIG)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_PAD)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_GPIO)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_FUSE)] = {1, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TRNG)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_USBP)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_LPUC)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART0)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART1)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_UART2)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_SPI0)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_SPI1)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2S0)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2S1)] = {0, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_WDG)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER0)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER1)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER2)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER3)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER4)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_TIMER5)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_IPC)] = {1, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2C0)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_I2C1)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_USIM0)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_USIM1)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_KPC)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PCLK_ONEW)] = {0, CLK_APB_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TOP_PBRG_HCLK)] = {1, CLK_CC_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TOP_PBRG_PCLK)] = {1, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TOP_GPR_PCLK)] = {1, CLK_APB_MP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TRACE_CLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ETM_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ROMTABLE_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TPIU_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(CACHE_HCLK)] = {1, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(FABSUB_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(SBU_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(PBRG_HCLK)] = {1, CLK_CC_AP, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(SPIS_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(XIC_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ULOG_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(TMU_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(SCT_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(UTFC_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(ULDP_RMI_HCLK)] = {0, INVALID_CLK, 0, 0},
[GET_INDEX_FROM_CLOCK_ID(SCT_HCLK)] = {0, INVALID_CLK, 0, 0},
};
PLAT_PA_RAMCODE void CLOCK_Trace(ClockId_e id, bool isEnable, void *func)
{
#ifdef PM_FEATURE_ENABLE
ClockId_e checkId = CLOCK_checkClkID();
uint32_t indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(id == checkId)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_Trace_1, P_WARNING, "Clock Trace, id=0x%x isEnable=%d counter=%d, funcPtr=%x", id, isEnable, g_clkTreeArray[indexFromId].enableCount, func);
}
if (g_clkTreeArray[indexFromId].enableCount > 128)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_Trace_2, P_WARNING, "Clock Trace, id=0x%x counter=%d may overflow, funcPtr=%x", id, g_clkTreeArray[indexFromId].enableCount, func);
}
#endif
}
void CLOCK_AssertChkBeforeSlp(void)
{
#ifdef PM_FEATURE_ENABLE
if(CLOCK_checkClkID() == INVALID_CLK)
return;
uint32_t indexFromId = GET_INDEX_FROM_CLOCK_ID(CLOCK_checkClkID());
if(g_clkTreeArray[indexFromId].enableCount != 0)
EC_ASSERT(0, g_clkTreeArray[indexFromId].enableCount, indexFromId, 0);
#endif
}
PLAT_PA_RAMCODE int32_t CLOCK_clockEnable(ClockId_e id)
{
#if defined(ENABLE_CLK_TREE_PARENT)
int32_t ret;
#endif
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(indexFromId > GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return ARM_DRIVER_ERROR_PARAMETER;
else if(indexFromId == GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return ARM_DRIVER_OK;
mask = SaveAndSetIRQMask();
CLOCK_Trace(id, true, __GET_RETURN_ADDRESS());
if(g_clkTreeArray[indexFromId].enableCount++ == 0)
{
GPR_clockEnable(id);
RestoreIRQMask(mask);
#if defined(ENABLE_CLK_TREE_PARENT)
if(g_clkTreeArray[indexFromId].hasExtraDependency)
{
ret = CLOCK_clockEnable(PBRG_HCLK);
ASSERT(ret == ARM_DRIVER_OK);
}
ret = CLOCK_clockEnable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
ASSERT(ret == ARM_DRIVER_OK);
#endif
}
else
{
if(GPR_clockEnableCheck(id) == false)
{
#ifdef PM_FEATURE_ENABLE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_clockEnable_1, P_WARNING, "Clock Enable Failed, id=0x%x counter=%d", id, g_clkTreeArray[indexFromId].enableCount);
#endif
ASSERT(0);
}
RestoreIRQMask(mask);
}
return ARM_DRIVER_OK;
}
PLAT_PA_RAMCODE void CLOCK_clockDisable(ClockId_e id)
{
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return;
mask = SaveAndSetIRQMask();
CLOCK_Trace(id, false, __GET_RETURN_ADDRESS());
if(g_clkTreeArray[indexFromId].enableCount == 0)
{
RestoreIRQMask(mask);
#ifdef PM_FEATURE_ENABLE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, CLOCK_clockDisable_0, P_WARNING, "Clock Disable check failed, id=0x%x", id);
#endif
ASSERT(0);
return;
}
if(!(--g_clkTreeArray[indexFromId].enableCount))
{
GPR_clockDisable(id);
RestoreIRQMask(mask);
#if defined(ENABLE_CLK_TREE_PARENT)
if(g_clkTreeArray[indexFromId].hasExtraDependency)
{
CLOCK_clockDisable(PBRG_HCLK);
}
CLOCK_clockDisable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
#endif
}
else
{
RestoreIRQMask(mask);
}
}
PLAT_PA_RAMCODE void CLOCK_clockReset(ClockId_e id)
{
uint32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
uint8_t count = 0;
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return;
mask = SaveAndSetIRQMask();
count = g_clkTreeArray[indexFromId].enableCount;
g_clkTreeArray[indexFromId].enableCount = 0;
GPR_clockDisable(id);
RestoreIRQMask(mask);
/* here, maybe not right */
#if defined(ENABLE_CLK_TREE_PARENT)
if(count > 0)
{
CLOCK_clockDisable((ClockId_e)g_clkTreeArray[indexFromId].parentId);
}
#endif
return;
}
int32_t CLOCK_setClockSrc(ClockId_e id, ClockSelect_e select)
{
int32_t ret, mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return ARM_DRIVER_ERROR_PARAMETER;
mask = SaveAndSetIRQMask();
if((g_clkTreeArray[indexFromId].enableCount == 0) || (g_clkTreeArray[indexFromId].canChangeSrcForcely == 1))
{
ret = GPR_setClockSrc(id, select);
if(ret == ARM_DRIVER_OK)
{
g_clkTreeArray[indexFromId].parentId = (ClockId_e)(GET_PARENTCLOCKID_FROM_CLOCK_SEL_VALUE(select));
}
RestoreIRQMask(mask);
return ret;
}
RestoreIRQMask(mask);
return ARM_DRIVER_ERROR;
}
int32_t CLOCK_setClockDiv(ClockId_e id, uint32_t div)
{
int32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return ARM_DRIVER_ERROR_PARAMETER;
mask = SaveAndSetIRQMask();
if(g_clkTreeArray[indexFromId].enableCount == 0)
{
RestoreIRQMask(mask);
return GPR_setClockDiv(id, div);
}
RestoreIRQMask(mask);
return ARM_DRIVER_ERROR;
}
uint32_t CLOCK_getClockFreq(ClockId_e id)
{
return GPR_getClockFreq(id);
}
int32_t CLOCK_setFracDivConfig(FracDivConfig_t * config)
{
if(config == NULL)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
else
{
if((config->fracDiv0DivRatioInteger == 256) && (config->fracDiv0DivRatioFrac != 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if((config->fracDiv1DivRatioInteger == 256) && (config->fracDiv1DivRatioFrac != 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
GPR_setFracDivConfig(config);
return ARM_DRIVER_OK;
}
}
void CLOCK_bclkEnable(BclkId_e id)
{
GPR_BclkEnable(id);
}
void CLOCK_fracDivOutCLkEnable(FracDivOutClkId_e id)
{
GPR_fracDivOutCLkEnable(id);
}
void CLOCK_fracDivOutClkDisable(FracDivOutClkId_e id)
{
GPR_fracDivOutClkDisable(id);
}
void CLOCK_setFracDivOutClkDiv(FracDivOutClkId_e id, uint8_t div)
{
GPR_setFracDivOutClkDiv(id, div);
}
void CLOCK_setBclkSrc(BclkId_e id, BclkSrc_e src)
{
GPR_setBclkSrc(id, src);
}
void CLOCK_setBclkDiv(BclkId_e id, uint8_t div)
{
GPR_setBclkDiv(id, div);
}
void CLOCK_setMclkSrc(MclkId_e id, MclkSrc_e src)
{
GPR_setMclkSrc(id, src);
}
void CLOCK_mclkEnable(MclkId_e id)
{
GPR_mclkEnable(id);
}
void CLOCK_mclkDisable(MclkId_e id)
{
GPR_mclkDisable(id);
}
void CLOCK_setMclkDiv(MclkId_e id, uint8_t div)
{
GPR_setMclkDiv(id, div);
}
void CLOCK_updateClockTreeElement(ClockId_e id, ClockId_e parentId, uint8_t enableCount)
{
int32_t mask, indexFromId = GET_INDEX_FROM_CLOCK_ID(id);
if(indexFromId >= GET_INDEX_FROM_CLOCK_ID(INVALID_CLK))
return;
mask = SaveAndSetIRQMask();
g_clkTreeArray[indexFromId].parentId = parentId;
g_clkTreeArray[indexFromId].enableCount = enableCount;
RestoreIRQMask(mask);
}

View File

@@ -0,0 +1,878 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: cspi.c
* Description: Dedicated spi for camera use in EC618. The interface is similar with CMSIS Driver API V2.0.
* History: Rev1.0 2021-03-18
*
****************************************************************************/
#include "cspi.h"
#include "slpman.h"
#include "cameraDrv.h"
//////////////////////////////////////////////////////////////////////////////////////////////
// CSPI Setting field Start
// All the CSPI's parameters that need user to set are all put here
//////////////////////////////////////////////////////////////////////////////////////////////
static DmaTransferConfig_t g_dmaRxConfig =
{
NULL,
NULL,
DMA_FLOW_CONTROL_SOURCE,
DMA_ADDRESS_INCREMENT_TARGET,
DMA_DATA_WIDTH_FOUR_BYTES,
DMA_BURST_32_BYTES,
0
};
#if (RTE_CSPI0)
static PIN cspi0PinMCLK = {RTE_CSPI0_MCLK_PAD_ADDR, RTE_CSPI0_MCLK_FUNC};
static PIN cspi0PinPCLK = {RTE_CSPI0_PCLK_PAD_ADDR, RTE_CSPI0_PCLK_FUNC};
static PIN cspi0PinCS = {RTE_CSPI0_CS_PAD_ADDR, RTE_CSPI0_CS_FUNC};
static PIN cspi0PinSdo0 = {RTE_CSPI0_SDO0_PAD_ADDR, RTE_CSPI0_SDO0_FUNC};
static PIN cspi0PinSdo1 = {RTE_CSPI0_SDO1_PAD_ADDR, RTE_CSPI0_SDO1_FUNC};
#elif (RTE_CSPI1)
static PIN cspi1PinMCLK = {RTE_CSPI1_MCLK_PAD_ADDR, RTE_CSPI1_MCLK_FUNC};
static PIN cspi1PinPCLK = {RTE_CSPI1_PCLK_PAD_ADDR, RTE_CSPI1_PCLK_FUNC};
static PIN cspi1PinCS = {RTE_CSPI1_CS_PAD_ADDR, RTE_CSPI1_CS_FUNC};
static PIN cspi1PinSdo0 = {RTE_CSPI1_SDO0_PAD_ADDR, RTE_CSPI1_SDO0_FUNC};
static PIN cspi1PinSdo1 = {RTE_CSPI1_SDO1_PAD_ADDR, RTE_CSPI1_SDO1_FUNC};
#endif
// Data Format
cspiDataFmt_t cspiDataFmt =
{
.slaveModeEn = 1,
.slotSize = 7,
.wordSize = 7,
.alignMode = 0,
.endianMode = 0, // 0:LSB 1: MSB.
.dataDly = 0,
.txPad = 0,
.rxSignExt = 0,
.txPack = 0,
.rxPack = 2,
.txFifoEndianMode = 0,
.rxFifoEndianMode = 0
};
// Frame Info0
cspiFrameInfo0_t cspiFrameInfo0 =
{
.cspiBusTimeOutCycle = 0x1000,
.dataId = 0, // readOnly
};
// RX Fifo timeout Cycle
cspiTimeOutCycle_t cspiRxTimeOutCycle =
{
.rxTimeOutCycle = 20,
};
// INT Control
cspiIntCtrl_t cspiIntCtrl =
{
.txUnderRunIntEn = 0,
.txDmaErrIntEn = 0,
.txDatIntEn = 0,
.rxOverFlowIntEn = 0,
.rxDmaErrIntEn = 0,
.rxDatIntEn = 0,
.rxTimeOutIntEn = 0,
.fsErrIntEn = 0,
.frameStartIntEn = 0,
.frameEndIntEn = 0,
.cspiBusTimeOutIntEn = 0,
.txIntThreshHold = 8,
.rxIntThreshHold = 8,
};
// DMA Control
cspiDmaCtrl_t cspiDmaCtrl =
{
.rxDmaReqEn = 1,
.txDmaReqEn = 0,
.rxDmaTimeOutEn = 0,
.dmaWorkWaitCycle = 31,
.rxDmaBurstSizeSub1 = 7,
.txDmaBurstSizeSub1 = 7,
.rxDmaThreadHold = 7,
.txDmaThreadHold = 8,
.rxFifoFlush = 0,
.txFifoFlush = 0
};
cspiCtrl_t cspiCtrl =
{
.enable = 0,
.csEn = 0,
.rxWid = 1, // 0: 1bit; 1: 2bit
.rxdSeq = 1, // gc032a 0, sp0a39 1
.cpol = 0,
.cpha = 1,
.frameProcEn = 1,
.fillYonly = 1,
.hwInitEn = 1,
.lsCheckEn = 1,
.dpCheckEn = 1,
.frameProcInitEn = 0,
.rowScaleRatio = 0,
.colScaleRatio = 0,
.scaleBytes = 0,
};
//////////////////////////////////////////////////////////////////////////////////////////////
// CSPI Setting field End
//////////////////////////////////////////////////////////////////////////////////////////////
static CSPI_TypeDef* const cspiInstance[CSPI_INSTANCE_NUM] = {CSPI0, CSPI1};
static ClockId_e cspiClk[CSPI_INSTANCE_NUM * 2] =
{
PCLK_I2S0,
FCLK_I2S0,
PCLK_I2S1,
FCLK_I2S1
};
static ClockResetId_e cspiRstClk[CSPI_INSTANCE_NUM * 2] =
{
RST_PCLK_I2S0,
RST_FCLK_I2S0,
RST_PCLK_I2S1,
RST_FCLK_I2S1
};
#ifdef PM_FEATURE_ENABLE
/**
\brief spi initialization counter, for lower power callback register/de-register
*/
static uint32_t cspiInitCnt = 0;
/**
\brief Bitmap of CSPI working status, each instance is assigned 2 bits representing tx and rx status,
when all CSPI instances are not working, we can vote to enter to low power state.
*/
static uint32_t cspiWorkingStats = 0;
/** \brief Internal used data structure */
typedef struct
{
bool isInited; /**< Whether spi has been initialized */
struct
{
__IO uint32_t DFMT; /**< Data Format Register, offset: 0x0 */
__IO uint32_t SLOTCTL; /**< Slot Control Register, offset: 0x4 */
__IO uint32_t CLKCTL; /**< Clock Control Register, offset: 0x8 */
__IO uint32_t DMACTL; /**< DMA Control Register, offset: 0xC */
__IO uint32_t INTCTL; /**< Interrupt Control Register, offset: 0x10 */
__IO uint32_t TIMEOUTCTL; /**< Timeout Control Register, offset: 0x14 */
__IO uint32_t STAS; /**< Status Register, offset: 0x18 */
__IO uint32_t RFIFO; /**< Rx Buffer Register, offset: 0x1c */
__IO uint32_t TFIFO; /**< Tx Buffer Register, offset: 0x20 */
__IO uint32_t CSPICTL; /**< Camera SPI Control Register, offset: 0x28 */
__IO uint32_t CCTL; /**< Auto Cg Control Register, offset: 0x2c */
__IO uint32_t CSPIINFO0; /**< Cspi Frame info0 Register, offset: 0x30 */
__IO uint32_t CSPIINFO1; /**< Cspi Frame info1 Register, offset: 0x34 */
__IO uint32_t CSPIDBG; /**< Cspi Debug Register, offset: 0x38 */
__IO uint32_t CSPINIT; /**< Cspi Init Register, offset: 0x3c */
__IO uint32_t CLSP; /**< Cspi Line Start Register, offset: 0x40 */
__IO uint32_t CDATP; /**< Cspi Data Packet Register, offset: 0x44 */
__IO uint32_t CLINFO; /**< Cspi Line Info Register, offset: 0x48 */
}regsBackup;
} cspiDataBase_t;
static cspiDataBase_t cspiDataBase[CSPI_INSTANCE_NUM] = {0};
/**
\fn static void cspiEnterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Perform necessary preparations before sleep.
After recovering from SLPMAN_SLEEP1_STATE, CSPI hareware is repowered, we backup
some registers here first so that we can restore user's configurations after exit.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void cspiEnterLpStatePrepare(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < CSPI_INSTANCE_NUM; i++)
{
if(cspiDataBase[i].isInited == true)
{
cspiDataBase[i].regsBackup.DFMT = cspiInstance[i]->DFMT;
cspiDataBase[i].regsBackup.SLOTCTL = cspiInstance[i]->SLOTCTL;
cspiDataBase[i].regsBackup.CLKCTL = cspiInstance[i]->CLKCTL;
cspiDataBase[i].regsBackup.DMACTL = cspiInstance[i]->DMACTL;
cspiDataBase[i].regsBackup.INTCTL = cspiInstance[i]->INTCTL;
cspiDataBase[i].regsBackup.TIMEOUTCTL = cspiInstance[i]->TIMEOUTCTL;
cspiDataBase[i].regsBackup.STAS = cspiInstance[i]->STAS;
cspiDataBase[i].regsBackup.CSPICTL = cspiInstance[i]->CSPICTL;
cspiDataBase[i].regsBackup.CCTL = cspiInstance[i]->CCTL;
cspiDataBase[i].regsBackup.CSPIINFO0 = cspiInstance[i]->CSPIINFO0;
cspiDataBase[i].regsBackup.CSPIINFO1 = cspiInstance[i]->CSPIINFO1;
cspiDataBase[i].regsBackup.CSPIDBG = cspiInstance[i]->CSPIDBG;
cspiDataBase[i].regsBackup.CSPINIT = cspiInstance[i]->CSPINIT;
cspiDataBase[i].regsBackup.CLSP = cspiInstance[i]->CLSP;
cspiDataBase[i].regsBackup.CDATP = cspiInstance[i]->CDATP;
cspiDataBase[i].regsBackup.CLINFO = cspiInstance[i]->CLINFO;
}
}
break;
default:
break;
}
}
/**
\fn static void cspiExitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore after exit from sleep.
After recovering from SLPMAN_SLEEP1_STATE, CSPI hareware is repowered, we restore user's configurations
by aidding of the stored registers.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void cspiExitLpStateRestore(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < CSPI_INSTANCE_NUM; i++)
{
if(cspiDataBase[i].isInited == true)
{
GPR_clockEnable(cspiClk[2*i]);
GPR_clockEnable(cspiClk[2*i+1]);
cspiInstance[i]->DFMT = cspiDataBase[i].regsBackup.DFMT;
cspiInstance[i]->SLOTCTL = cspiDataBase[i].regsBackup.SLOTCTL;
cspiInstance[i]->CLKCTL = cspiDataBase[i].regsBackup.CLKCTL;
cspiInstance[i]->DMACTL = cspiDataBase[i].regsBackup.DMACTL;
cspiInstance[i]->INTCTL = cspiDataBase[i].regsBackup.INTCTL;
cspiInstance[i]->TIMEOUTCTL = cspiDataBase[i].regsBackup.TIMEOUTCTL;
cspiInstance[i]->STAS = cspiDataBase[i].regsBackup.STAS;
cspiInstance[i]->CSPICTL = cspiDataBase[i].regsBackup.CSPICTL;
cspiInstance[i]->CCTL = cspiDataBase[i].regsBackup.CCTL;
cspiInstance[i]->CSPIINFO0 = cspiDataBase[i].regsBackup.CSPIINFO0;
cspiInstance[i]->CSPIINFO1 = cspiDataBase[i].regsBackup.CSPIINFO1;
cspiInstance[i]->CSPIDBG = cspiDataBase[i].regsBackup.CSPIDBG;
cspiInstance[i]->CSPINIT = cspiDataBase[i].regsBackup.CSPINIT;
cspiInstance[i]->CLSP = cspiDataBase[i].regsBackup.CLSP;
cspiInstance[i]->CDATP = cspiDataBase[i].regsBackup.CDATP;
cspiInstance[i]->CLINFO = cspiDataBase[i].regsBackup.CLINFO;
}
}
break;
default:
break;
}
}
#define LOCK_SLEEP(instance) \
do \
{ \
cspiWorkingStats |= (1U << instance); \
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_ACTIVE_STATE); \
} \
while(0)
#define CHECK_TO_UNLOCK_SLEEP(instance) \
do \
{ \
cspiWorkingStats &= ~(1U << instance); \
if(cspiWorkingStats == 0) \
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_SLP1_STATE); \
} \
while(0)
#endif
#if (RTE_CSPI0)
static cspiInfo_t cspi0Info = {0};
void cspi0DmaRxEvent(uint32_t event);
static DmaDescriptor_t __ALIGNED(16) cspi0DmaRxDesc[CAM_CHAIN_COUNT];
static cspiDma_t cspi0Dma =
{
DMA_INSTANCE_MP,
-1,
RTE_CSPI0_DMA_RX_REQID,
cspi0DmaRxEvent,
cspi0DmaRxDesc
};
static cspiRes_t cspi0Res = {
CSPI0,
{
&cspi0PinMCLK,
&cspi0PinPCLK,
&cspi0PinCS,
&cspi0PinSdo0,
&cspi0PinSdo1,
},
&cspi0Dma,
&cspi0Info
};
#endif
#if (RTE_CSPI1)
static cspiInfo_t cspi1Info = {0};
void cspi1DmaRxEvent(uint32_t event);
static DmaDescriptor_t __ALIGNED(16) cspi1DmaRxDesc[CAM_CHAIN_COUNT];
static cspiDma_t cspi1Dma =
{
DMA_INSTANCE_MP,
-1,
RTE_CSPI1_DMA_RX_REQID,
cspi1DmaRxEvent,
cspi1DmaRxDesc
};
static cspiRes_t cspi1Res = {
CSPI1,
{
&cspi1PinMCLK,
&cspi1PinPCLK,
&cspi1PinCS,
&cspi1PinSdo0,
&cspi1PinSdo1,
},
&cspi1Dma,
&cspi1Info
};
#endif
/**
\fn static uint32_t cspiGetInstanceNum(cspiRes_t *cspi)
\brief Get instance number
\param[in] spi Pointer to CSPI resources
\returns instance number
*/
static uint32_t cspiGetInstanceNum(cspiRes_t *cspi)
{
return ((uint32_t)cspi->reg - (uint32_t)CSPI0) >> 12U;
}
/**
\fn static int32_t cspiSetBusSpeed(uint32_t bps, cspiRes_t *cspi)
\brief Set bus speed
\param[in] bps bus speed to set
\param[in] spi Pointer to SPI resources
\return \ref execution_status
*/
static int32_t cspiSetBusSpeed(camFrequence_e freq, cspiRes_t *cspi)
{
uint32_t instance = cspiGetInstanceNum(cspi);
uint32_t freqDivInteger = 0;
uint32_t freqDivRatio = 0;
switch(freq)
{
case CAM_6_5_M:
freqDivInteger = 0x40;
freqDivRatio = 0;
break;
case CAM_13_M:
freqDivInteger = 0x20;
freqDivRatio = 0;
break;
case CAM_25_5_M:
freqDivInteger = 0x10;
freqDivRatio = 0;
break;
case CAM_24_M:
freqDivInteger = 0x11;
freqDivRatio = 0;
break;
case CAM_20_M:
freqDivInteger = 0x14;
freqDivRatio = 0x666666;
break;
default:
break;
}
if (instance == 0) // i2s0
{
GPR_clockEnable(FCLK_I2S0);
GPR_fracDivOutCLkEnable(FRACDIV0_OUT0); // Fracdiv1_en
GPR_setFracDivOutClkDiv(FRACDIV0_OUT0, 1); // 4 div, from 408M -> 102M
#if 1
GPR_setMclkSrc(MCLK0, MCLK_SRC_FRACDIV0_OUT0); // Bmclk_sel1
GPR_mclkEnable(MCLK0); // Mclk_oe1
#else
GPR_setMclkSrc(MCLK2, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
GPR_mclkEnable(MCLK2);
#endif
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // 0x4d000020 = 0x201
// Fracdiv clk selects 408M and set frac and integer clk
FracDivConfig_t fracdivCfg;
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
fracdivCfg.fracDiv0DivRatioInteger = freqDivInteger;//0x10;//51M 0x10; // 25.5M
fracdivCfg.fracDiv0DivRatioFrac = freqDivRatio;
GPR_setFracDivConfig(&fracdivCfg);
}
else // i2s1
{
GPR_clockEnable(FCLK_I2S1);
GPR_fracDivOutCLkEnable(FRACDIV1_OUT0); // Fracdiv1_en
GPR_setFracDivOutClkDiv(FRACDIV1_OUT0, 1); // 4 div, from 408M -> 102M
#if 1
GPR_setMclkSrc(MCLK1, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
GPR_mclkEnable(MCLK1); // Mclk_oe1
#else
GPR_setMclkSrc(MCLK2, MCLK_SRC_FRACDIV1_OUT0); // Bmclk_sel1
GPR_mclkEnable(MCLK2);
#endif
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // 0x4d000020 = 0x201
// Fracdiv clk selects 408M and set frac and integer clk
FracDivConfig_t fracdivCfg;
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
fracdivCfg.fracDiv1DivRatioInteger = freqDivInteger;//0x10;//51M 0x10; // 25.5M
fracdivCfg.fracDiv1DivRatioFrac = freqDivRatio;
GPR_setFracDivConfig(&fracdivCfg);
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t cspiInit(cspiCbEvent_fn cbEvent, cspiRes_t *cspi)
\brief Initialize SPI Interface.
\param[in] cbEvent Pointer to \ref cspiCbEvent_fn
\param[in] spi Pointer to CSPI resources
\return \ref execution_status
*/
int32_t cspiInit(cspiCbEvent_fn cbEvent, cspiRes_t *cspi)
{
int32_t returnCode;
PadConfig_t config;
uint32_t instance = cspiGetInstanceNum(cspi);
#ifdef PM_FEATURE_ENABLE
cspiDataBase[instance].isInited = true;
#endif
// Initialize CSPI PINS
PAD_getDefaultConfig(&config);
#if 1 // I2S1
config.mux = cspi->pins.mclk->funcNum;
PAD_setPinConfig(cspi->pins.mclk->pinNum, &config);
#else // MCLK2
config.mux = PAD_MUX_ALT1;
PAD_setPinConfig(14, &config);
#endif
config.mux = cspi->pins.pclk->funcNum;
PAD_setPinConfig(cspi->pins.pclk->pinNum, &config);
config.mux = cspi->pins.cs->funcNum;
PAD_setPinConfig(cspi->pins.cs->pinNum, &config);
config.mux = cspi->pins.sdo0->funcNum;
PAD_setPinConfig(cspi->pins.sdo0->pinNum, &config);
config.mux = cspi->pins.sdo1->funcNum;
PAD_setPinConfig(cspi->pins.sdo1->pinNum, &config);
// Initialize SPI run-time resources
cspi->info->cbEvent = cbEvent;
// Configure DMA if necessary
if (cspi->dma)
{
DMA_init(cspi->dma->rxInstance);
returnCode = DMA_openChannel(cspi->dma->rxInstance);
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
return ARM_DRIVER_ERROR;
else
cspi->dma->rxCh = returnCode;
DMA_setChannelRequestSource(cspi->dma->rxInstance, cspi->dma->rxCh, (DmaRequestSource_e)cspi->dma->rxReq);
DMA_rigisterChannelCallback(cspi->dma->rxInstance, cspi->dma->rxCh, cspi->dma->rxCb);
// Configure rx DMA and start it
g_dmaRxConfig.sourceAddress = (void *)&(cspiInstance[instance]->RFIFO);
g_dmaRxConfig.totalLength = CSPI_TRANSFER_TRUNK_SIZE;
DMA_enableChannelInterrupts(cspi->dma->rxInstance, cspi->dma->rxCh, DMA_END_INTERRUPT_ENABLE);
DMA_startChannel(cspi->dma->rxInstance, cspi->dma->rxCh);
}
#ifdef PM_FEATURE_ENABLE
cspiInitCnt++;
if(cspiInitCnt == 1U)
{
cspiWorkingStats = 0;
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE, cspiEnterLpStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE, cspiExitLpStateRestore, NULL);
}
#endif
return ARM_DRIVER_OK;
}
/**
\fn int32_t cspiDeInit(cspiRes_t *cspi)
\brief De-initialize CSPI Interface.
\param[in] spi Pointer to CSPI resources
\return \ref execution_status
*/
int32_t cspiDeInit(cspiRes_t *cspi)
{
#ifdef PM_FEATURE_ENABLE
uint32_t instance;
instance = cspiGetInstanceNum(cspi);
cspiDataBase[instance].isInited = false;
cspiInitCnt--;
if(cspiInitCnt == 0)
{
cspiWorkingStats = 0;
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE);
}
#endif
return ARM_DRIVER_OK;
}
/**
\fn int32_t cspiPowerControl(cspiPowerState_e state, cspiRes_t *cspi)
\brief Control CSPI Interface Power.
\param[in] state Power state
\param[in] cspi Pointer to CSPI resources
\return \ref execution_status
*/
int32_t cspiPowerCtrl(cspiPowerState_e state, cspiRes_t *cspi)
{
uint32_t instance = cspiGetInstanceNum(cspi);
switch (state)
{
case CSPI_POWER_OFF:
// DMA disable
if(cspi->dma)
{
DMA_stopChannel(cspi->dma->rxInstance, cspi->dma->rxCh, true);
}
// Reset register values
if (instance == 0)
{
CLOCK_setClockSrc(FCLK_I2S0, FCLK_I2S0_SEL_26M);
GPR_swReset(RST_PCLK_I2S0);
}
else
{
CLOCK_setClockSrc(FCLK_I2S1, FCLK_I2S1_SEL_26M);
GPR_swReset(RST_PCLK_I2S1);
}
// Disable CSPI clock
GPR_clockDisable(cspiClk[instance*2]);
GPR_clockDisable(cspiClk[instance*2+1]);
cspi->info->flags &= ~CSPI_FLAG_POWERED;
break;
case CSPI_POWER_FULL:
//if ((cspi->info->flags & CSPI_FLAG_INITIALIZED) == 0)
//return ARM_DRIVER_ERROR;
if (cspi->info->flags & CSPI_FLAG_POWERED)
return ARM_DRIVER_OK;
// Enable CSPI clock
GPR_clockEnable(cspiClk[instance*2]);
GPR_clockEnable(cspiClk[instance*2+1]);
GPR_swReset(cspiRstClk[instance*2]);
GPR_swReset(cspiRstClk[instance*2+1]);
// Set power flag
cspi->info->flags |= CSPI_FLAG_POWERED;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t cspiReceive(void *data, uint32_t num, cspiRes_t *cspi)
\brief Start receiving data from SPI receiver.
\param[out] dataIn Pointer to buffer for data to receive from CSPI receiver
\param[in] num Number of data items to receive
\param[in] cspi Pointer to CSPI resources
\return \ref execution_status
*/
int32_t cspiRecv(cspiRes_t *cspi)
{
DMA_buildDescriptorChain(cspi->dma->descriptor, &g_dmaRxConfig, cspi->info->resolution, true);
DMA_loadChannelDescriptorAndRun(cspi->dma->rxInstance, cspi->dma->rxCh, cspi->dma->descriptor);
return ARM_DRIVER_OK;
}
/**
\fn int32_t cspiControl(uint32_t control, uint32_t arg, cspiRes_t *cspi)
\brief Control CSPI Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\param[in] cspi Pointer to CSPI resources
\return common \ref execution_status and driver specific \ref spi_execution_status
*/
int32_t cspiControl(uint32_t control, uint32_t arg, cspiRes_t *cspi)
{
uint32_t instance = cspiGetInstanceNum(cspi);
switch(control & 0xFFFFFFFF)
{
// Set transport abort
case CSPI_CTRL_TRANSABORT:
{
// If DMA mode, disable DMA channel
if(cspi->dma)
{
DMA_stopChannel(cspi->dma->rxInstance, cspi->dma->rxCh, true);
}
// clear SPI run-time resources
cspi->reg->CSPICTL &= ~CSPI_ENABLE_Msk;
break;
}
// Set Bus Speed in bps; arg = value
case CSPI_CTRL_BUS_SPEED:
{
if(cspiSetBusSpeed((camFrequence_e)arg, cspi) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
break;
}
// Set Data Format
case CSPI_CTRL_DATA_FORMAT:
{
memcpy((void*)&(cspiInstance[instance]->DFMT), &cspiDataFmt, sizeof(cspiDataFmt_t));
break;
}
// Flush rx fifo
case CSPI_CTRL_FLUSH_RX_FIFO:
{
cspiInstance[instance]->DMACTL |= 0x1000000;
break;
}
// Set Int En
case CSPI_CTRL_INT_CTRL:
{
memcpy((void*)&(cspiInstance[instance]->INTCTL), &cspiIntCtrl, sizeof(cspiIntCtrl_t));
break;
}
// Set recv mem addr
case CSPI_CTRL_MEM_ADDR:
{
g_dmaRxConfig.targetAddress = (void*)arg; // dma gloval val. After this need call "CSPI_CTRL_DMA_CTRL"
break;
}
// Set Rx Timeout Cycle
case CSPI_CTRL_RXTOR:
{
memcpy((void*)&(cspiInstance[instance]->TIMEOUTCTL), &cspiRxTimeOutCycle, sizeof(cspiTimeOutCycle_t));
break;
}
// Set DMA Control
case CSPI_CTRL_DMA_CTRL:
{
//dmaInit(cspi);
memcpy((void*)&(cspiInstance[instance]->DMACTL), &cspiDmaCtrl, sizeof(cspiDmaCtrl_t));
break;
}
// Set CSPI Control
case CSPI_CTRL_CSPICTL:
{
memcpy((void*)&(cspiInstance[instance]->CSPICTL), &cspiCtrl, sizeof(cspiCtrl_t));
break;
}
// Enable or disable cspi
case CSPI_CTRL_START_STOP:
{
if (arg > 0)
{
cspiInstance[instance]->CSPICTL |= CSPI_ENABLE_Msk;
}
else
{
cspiInstance[instance]->CSPICTL &= ~CSPI_ENABLE_Msk;
}
break;
}
// Set Frame Info0
case CSPI_CTRL_FRAME_INFO0:
{
memcpy((void*)&(cspiInstance[instance]->CSPIINFO0), &cspiFrameInfo0, sizeof(cspiFrameInfo0_t));
break;
}
// Camera resolution set
case CSPI_CTRL_RESOLUTION_SET:
{
cspi->info->resolution = (camResolution_e)arg; // this will interface the dma descriptor chain count
break;
}
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
/**
\fn void cspiDmaRxEvent(uint32_t event, cspiRes_t *cspi)
\brief CSPI DMA Rx Event handler.
\param[in] event DMA Rx Event
\param[in] spi Pointer to CSPI resources
*/
void cspiDmaRxEvent(uint32_t event, cspiRes_t *cspi)
{
#ifdef PM_FEATURE_ENABLE
uint32_t instance = cspiGetInstanceNum(cspi);
#endif
switch(event)
{
case DMA_EVENT_END:
//cspi->reg->CSPICTL &= ~CSPI_ENABLE_Msk; // must close cspi here
if(cspi->info->cbEvent)
{
cspi->info->cbEvent(ARM_SPI_EVENT_TRANSFER_COMPLETE);
}
#ifdef PM_FEATURE_ENABLE
CHECK_TO_UNLOCK_SLEEP(instance);
#endif
break;
default:
break;
}
}
#if (RTE_CSPI0)
static int32_t cspi0Init(cspiCbEvent_fn cbEvent)
{
return cspiInit(cbEvent, &cspi0Res);
}
static int32_t cspi0Deinit(void)
{
return cspiDeInit(&cspi0Res);
}
static int32_t cspi0PowerCtrl(cspiPowerState_e state)
{
return cspiPowerCtrl(state, &cspi0Res);
}
static int32_t cspi0Recv(void)
{
return cspiRecv(&cspi0Res);
}
static int32_t cspi0Ctrl(uint32_t control, uint32_t arg)
{
return cspiControl(control, arg, &cspi0Res);
}
void cspi0DmaRxEvent(uint32_t event)
{
cspiDmaRxEvent(event, &cspi0Res);
}
// CSPI0 Driver Control Block
cspiDrvInterface_t cspiDrvInterface0 = {
cspi0Init,
cspi0Deinit,
cspi0PowerCtrl,
cspi0Recv,
cspi0Ctrl,
};
#endif
#if (RTE_CSPI1)
static int32_t cspi1Init(cspiCbEvent_fn cbEvent)
{
return cspiInit(cbEvent, &cspi1Res);
}
static int32_t cspi1Deinit(void)
{
return cspiDeInit(&cspi1Res);
}
static int32_t cspi1PowerCtrl(cspiPowerState_e state)
{
return cspiPowerCtrl(state, &cspi1Res);
}
static int32_t cspi1Recv(void)
{
return cspiRecv(&cspi1Res);
}
static int32_t cspi1Ctrl(uint32_t control, uint32_t arg)
{
return cspiControl(control, arg, &cspi1Res);
}
void cspi1DmaRxEvent(uint32_t event)
{
cspiDmaRxEvent(event, &cspi1Res);
}
// CSPI1 Driver Control Block
cspiDrvInterface_t cspiDrvInterface1 = {
cspi1Init,
cspi1Deinit,
cspi1PowerCtrl,
cspi1Recv,
cspi1Ctrl,
};
#endif

View File

@@ -0,0 +1,199 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: gpio.c
* Description: EC618 gpio driver source file
* History:
*
****************************************************************************/
#include "gpio.h"
#include "clock.h"
#include "slpman.h"
#define EIGEN_GPIO(n) ((GPIO_TypeDef *) (MP_GPIO_BASE_ADDR + 0x1000*n))
/**
\brief GPIO stutas flag
*/
static uint32_t gGpioStatus = 0;
#ifdef PM_FEATURE_ENABLE
/**
\fn void GPIO_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Backup gpio configurations before sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void GPIO_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
{
return;
}
/**
\fn void GPIO_exitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore gpio configurations after exit from sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void GPIO_exitLowPowerStateRestore(void* pdata, slpManLpState state)
{
switch (state)
{
case SLPMAN_SLEEP1_STATE:
if(gGpioStatus & 0x1U)
{
GPR_clockEnable(PCLK_GPIO);
}
break;
default:
break;
}
}
#endif
void GPIO_driverInit(void)
{
if((gGpioStatus & 0x1U) == 0)
{
#ifdef PM_FEATURE_ENABLE
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_GPIO_MODULE, GPIO_enterLowPowerStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_GPIO_MODULE, GPIO_exitLowPowerStateRestore, NULL);
#endif
CLOCK_clockEnable(PCLK_GPIO);
gGpioStatus = 0x1U;
}
}
void GPIO_driverDeInit(void)
{
gGpioStatus = 0;
// disable clock
CLOCK_clockDisable(PCLK_GPIO);
#ifdef PM_FEATURE_ENABLE
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_GPIO_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_GPIO_MODULE);
#endif
}
void GPIO_pinConfig(uint32_t port, uint16_t pin, const GpioPinConfig_t *config)
{
ASSERT(port < GPIO_INSTANCE_NUM);
uint16_t pinMask = 0x1U << pin;
GPIO_TypeDef *base = EIGEN_GPIO(port);
GPIO_driverInit();
switch(config->pinDirection)
{
case GPIO_DIRECTION_INPUT:
base->OUTENCLR = pinMask;
GPIO_interruptConfig(port, pin, config->misc.interruptConfig);
break;
case GPIO_DIRECTION_OUTPUT:
GPIO_pinWrite(port, pinMask, ((uint16_t)config->misc.initOutput) << pin);
base->OUTENSET = pinMask;
break;
default:
break;
}
}
void GPIO_interruptConfig(uint32_t port, uint16_t pin, GpioInterruptConfig_e config)
{
uint16_t pinMask = 0x1U << pin;
GPIO_TypeDef *base = EIGEN_GPIO(port);
switch(config)
{
case GPIO_INTERRUPT_DISABLED:
base->INTENCLR = pinMask;
break;
case GPIO_INTERRUPT_LOW_LEVEL:
base->INTPOLCLR = pinMask;
base->INTTYPECLR = pinMask;
base->INTENSET = pinMask;
break;
case GPIO_INTERRUPT_HIGH_LEVEL:
base->INTPOLSET = pinMask;
base->INTTYPECLR = pinMask;
base->INTENSET = pinMask;
break;
case GPIO_INTERRUPT_FALLING_EDGE:
base->INTPOLCLR = pinMask;
base->INTTYPESET = pinMask;
base->INTENSET = pinMask;
break;
case GPIO_INTERRUPT_RISING_EDGE:
base->INTPOLSET = pinMask;
base->INTTYPESET = pinMask;
base->INTENSET = pinMask;
break;
default :
break;
}
}
void GPIO_pinWrite(uint32_t port, uint16_t pinMask, uint16_t output)
{
EIGEN_GPIO(port)->MASKLOWBYTE[pinMask & 0xFFU] = output;
EIGEN_GPIO(port)->MASKHIGHBYTE[pinMask >> 8U] = output;
}
uint32_t GPIO_pinRead(uint32_t port, uint16_t pin)
{
return (((EIGEN_GPIO(port)->DATA) >> pin) & 0x01U);
}
uint16_t GPIO_getInterruptFlags(uint32_t port)
{
return EIGEN_GPIO(port)->INTSTATUS;
}
void GPIO_clearInterruptFlags(uint32_t port, uint16_t mask)
{
EIGEN_GPIO(port)->INTSTATUS = mask;
}
uint16_t GPIO_saveAndSetIrqMask(uint32_t port)
{
uint16_t mask = EIGEN_GPIO(port)->INTENSET;
EIGEN_GPIO(port)->INTENCLR = 0xFFFFU;
return mask;
}
void GPIO_restoreIrqMask(uint32_t port, uint16_t mask)
{
EIGEN_GPIO(port)->INTENSET = mask;
}

View File

@@ -0,0 +1,962 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: i2s.c
* Description: Audio use in EC618. The interface is similar with CMSIS Driver API V2.0.
* History: Rev1.0 2021-06-23
*
****************************************************************************/
#include "i2s.h"
#include "slpman.h"
//////////////////////////////////////////////////////////////////////////////////////////////
// I2S Setting field Start
// All the I2S's parameters that need user to set are all put here
//////////////////////////////////////////////////////////////////////////////////////////////
static DmaTransferConfig_t g_dmaTxConfig =
{
NULL,
NULL,
DMA_FLOW_CONTROL_TARGET,
DMA_ADDRESS_INCREMENT_SOURCE,
DMA_DATA_WIDTH_FOUR_BYTES,
DMA_BURST_64_BYTES,
0
};
static DmaTransferConfig_t g_dmaRxConfig =
{
NULL,
NULL,
DMA_FLOW_CONTROL_SOURCE,
DMA_ADDRESS_INCREMENT_TARGET,
DMA_DATA_WIDTH_TWO_BYTES,
DMA_BURST_8_BYTES,
0
};
#if (RTE_I2S0)
static PIN i2s0PinMCLK = {RTE_I2S0_MCLK_PAD_ADDR, RTE_I2S0_MCLK_FUNC};
static PIN i2s0PinBCLK = {RTE_I2S0_BCLK_PAD_ADDR, RTE_I2S0_BCLK_FUNC};
static PIN i2s0PinLRCK = {RTE_I2S0_LRCK_PAD_ADDR, RTE_I2S0_LRCK_FUNC};
static PIN i2s0PinDin = {RTE_I2S0_DIN_PAD_ADDR, RTE_I2S0_DIN_FUNC};
static PIN i2s0PinDout = {RTE_I2S0_DOUT_PAD_ADDR, RTE_I2S0_DOUT_FUNC};
#elif (RTE_I2S1)
static PIN i2s1PinMCLK = {RTE_I2S1_MCLK_PAD_ADDR, RTE_I2S1_MCLK_FUNC};
static PIN i2s1PinBCLK = {RTE_I2S1_BCLK_PAD_ADDR, RTE_I2S1_BCLK_FUNC};
static PIN i2s1PinLRCK = {RTE_I2S1_LRCK_PAD_ADDR, RTE_I2S1_LRCK_FUNC};
static PIN i2s1PinDin = {RTE_I2S1_DIN_PAD_ADDR, RTE_I2S1_DIN_FUNC};
static PIN i2s1PinDout = {RTE_I2S1_DOUT_PAD_ADDR, RTE_I2S1_DOUT_FUNC};
#endif
// Sample rate, fs, fracdiv part, integer part. Generate MClk accoding to the sample rate.
const uint32_t i2sSampleRateTbl[][4] =
{
{SAMPLE_RATE_8K, 256, 0xCE0000, 0x31}, // 256fs, 8k
{SAMPLE_RATE_16K, 256, 0xE70000, 0x18}, // 256fs, 16k
{SAMPLE_RATE_32K, 256, 0x738000, 0x0C}, // 256fs, 32k
{SAMPLE_RATE_22_05K,256, 0x11D9B0, 0x12}, // 256fs, 22.05k
{SAMPLE_RATE_44_1K, 256, 0x08ECD8, 0x09}, // 256fs, 44.1k
{SAMPLE_RATE_48K, 256, 0x4D0000, 0x08}, // 256fs, 48k
{SAMPLE_RATE_96K, 256, 0x268000, 0x04}, // 256fs, 96k
};
// Data Format
i2sDataFmt_t i2sDataFmt =
{
.slaveModeEn = 0x1, // 0:Master; 1:Slave mode
.slotSize = 0xf, // Slot size
.wordSize = 0xf, // Real word size
.alignMode = 0, // 1: Right alignment; 0: Left alignment
.endianMode = 0x1, // 1: MSB; 0: LSB
.dataDly = 0, // Used by I2S format
.txPad = 0, // Tx padding
.rxSignExt = 0, // Rx sign external
.txPack = 1, // 0: not compress; 1: 1word; 2: 2word
.rxPack = 0, // 0: not compress; 1: 1word; 2: 2word
.txFifoEndianMode = 0, // I2s use or cspi use?
.rxFifoEndianMode = 0, // I2s use or cspi use?
};
// Slot Control
i2sSlotCtrl_t i2sSlotCtrl =
{
.slotEn = 0x1, // Total 8 channels
.slotNum = 0x1 // For I2S, this value should be 1; For PCM, it can change
};
// BclkFs Control
i2sBclkFsCtrl_t i2sBclkFsCtrl =
{
.bclkPolarity = 1, // 0: Rising edge send, falling edge sample; 1: falling edge send, rising edge sample
.fsPolarity = 0, // 0: rising edge start; 1: falling edge start
.fsWidth = 0xf // fsWidth = slotNum * slotSize
};
// I2S Control
i2sCtrl_t i2sCtrl =
{
.i2sMode = 1, // 0: disable; 1: Only send; 2: Only receive; 3: Send and Receive
};
// DMA Control
i2sDmaCtrl_t i2sDmaCtrl =
{
.rxDmaReqEn = 0, // rx dma enable
.txDmaReqEn = 1, // tx dma enable
.rxDmaTimeOutEn = 0, // rx dma timeout enable
.dmaWorkWaitCycle = 31, // dma wait cycle number
.rxDmaBurstSizeSub1 = 7, // rx dma burst size -1
.txDmaBurstSizeSub1 = 15, // tx dma burst size -1
.rxDmaThreadHold = 8, // rx dma threshold
.txDmaThreadHold = 15, // tx dma threshold
.rxFifoFlush = 0, // flush rx fifo
.txFifoFlush = 0 // flush tx fifo
};
//////////////////////////////////////////////////////////////////////////////////////////////
// I2S Setting field End
//////////////////////////////////////////////////////////////////////////////////////////////
#if (RTE_I2S0)
static i2sInfo_t i2s0Info = {0};
void i2s0DmaRxEvent(uint32_t event);
void i2s0DmaTxEvent(uint32_t event);
DmaDescriptor_t __ALIGNED(16) i2s0DmaTxDesc[I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM];
DmaDescriptor_t __ALIGNED(16) i2s0DmaRxDesc[I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM];
#if (RTE_I2S0_IO_MODE == DMA_MODE)
static i2sDma_t i2s0Dma =
{
DMA_INSTANCE_MP,
-1,
RTE_I2S0_DMA_TX_REQID,
i2s0DmaTxEvent,
i2s0DmaTxDesc,
DMA_INSTANCE_MP,
-1,
RTE_I2S0_DMA_RX_REQID,
i2s0DmaRxEvent,
i2s0DmaRxDesc
};
#endif
static i2sResources_t i2s0Res = {
I2S0,
{
&i2s0PinMCLK,
&i2s0PinBCLK,
&i2s0PinLRCK,
&i2s0PinDin,
&i2s0PinDout,
},
#if (RTE_I2S0_IO_MODE == DMA_MODE)
&i2s0Dma,
#else
NULL,
#endif
NULL,
&i2s0Info
};
#endif
#if (RTE_I2S1)
static i2sInfo_t i2s1Info = {0};
void i2s1DmaRxEvent(uint32_t event);
void i2s1DmaTxEvent(uint32_t event);
static DmaDescriptor_t __ALIGNED(16) i2s1DmaTxDesc[I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM];
static DmaDescriptor_t __ALIGNED(16) i2s1DmaRxDesc[I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM];
static i2sDma_t i2s1Dma =
{
DMA_INSTANCE_MP,
-1,
RTE_I2S1_DMA_TX_REQID,
i2s1DmaTxEvent,
i2s1DmaTxDesc,
DMA_INSTANCE_MP,
-1,
RTE_I2S1_DMA_RX_REQID,
i2s1DmaRxEvent,
i2s1DmaRxDesc
};
static i2sResources_t i2s1Res = {
I2S1,
{
&i2s1PinMCLK,
&i2s1PinBCLK,
&i2s1PinLRCK,
&i2s1PinDin,
&i2s1PinDout,
},
#if (RTE_I2S1_IO_MODE == DMA_MODE)
&i2s1Dma,
#else
NULL,
#endif
NULL,
&i2s1Info
};
#endif
static I2S_TypeDef* const i2sInstance[I2S_INSTANCE_NUM] = {I2S0, I2S1};
static ClockId_e i2sClk[I2S_INSTANCE_NUM * 2] =
{
PCLK_I2S0,
FCLK_I2S0,
PCLK_I2S1,
FCLK_I2S1
};
static ClockId_e i2sMClk[I2S_INSTANCE_NUM] =
{
MCLK0,
MCLK1,
};
static ClockResetId_e i2sRstClk[I2S_INSTANCE_NUM * 2] =
{
RST_PCLK_I2S0,
RST_FCLK_I2S0,
RST_PCLK_I2S1,
RST_FCLK_I2S1
};
#ifdef PM_FEATURE_ENABLE
/** \brief Internal used data structure */
typedef struct
{
bool isInited; /**< Whether spi has been initialized */
bool mclkHasBeenClosed; /**< 1: mclk has been closed; 0: mclk hasn't been closed */
struct
{
__IO uint32_t DFMT; /**< Data Format Register, offset: 0x0 */
__IO uint32_t SLOTCTL; /**< Slot Control Register, offset: 0x4 */
__IO uint32_t CLKCTL; /**< Clock Control Register, offset: 0x8 */
__IO uint32_t DMACTL; /**< DMA Control Register, offset: 0xC */
__IO uint32_t INTCTL; /**< Interrupt Control Register, offset: 0x10 */
__IO uint32_t TIMEOUTCTL; /**< Timeout Control Register, offset: 0x14 */
__IO uint32_t STAS; /**< Status Register, offset: 0x18 */
__IO uint32_t RFIFO; /**< Rx Buffer Register, offset: 0x1c */
__IO uint32_t TFIFO; /**< Tx Buffer Register, offset: 0x20 */
__IO uint32_t I2SCTL; /**< I2S Control Register, offset: 0x28 */
}regsBackup;
} i2sDataBase_t;
static i2sDataBase_t i2sDataBase[I2S_INSTANCE_NUM] = {0};
/**
\brief i2s initialization counter, for lower power callback register/de-register
*/
static uint32_t i2sInitCnt = 0;
/**
\brief Bitmap of I2S working status, each instance is assigned 2 bits representing tx and rx status,
when all I2S instances are not working, we can vote to enter to low power state.
*/
volatile uint32_t i2sWorkingStats = 0;
/**
\fn static void i2sEnterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Perform necessary preparations before sleep.
After recovering from SLPMAN_SLEEP1_STATE, I2S hareware is repowered, we backup
some registers here first so that we can restore user's configurations after exit.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void i2sEnterLpStatePrepare(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < I2S_INSTANCE_NUM; i++)
{
if(i2sDataBase[i].isInited == true)
{
GPR_mclkDisable(i2sMClk[i]); // before sleep, disable MCLK
i2sDataBase[i].mclkHasBeenClosed = true;
i2sDataBase[i].regsBackup.DFMT = i2sInstance[i]->DFMT;
i2sDataBase[i].regsBackup.SLOTCTL = i2sInstance[i]->SLOTCTL;
i2sDataBase[i].regsBackup.CLKCTL = i2sInstance[i]->CLKCTL;
i2sDataBase[i].regsBackup.DMACTL = i2sInstance[i]->DMACTL;
i2sDataBase[i].regsBackup.INTCTL = i2sInstance[i]->INTCTL;
i2sDataBase[i].regsBackup.TIMEOUTCTL = i2sInstance[i]->TIMEOUTCTL;
i2sDataBase[i].regsBackup.STAS = i2sInstance[i]->STAS;
i2sDataBase[i].regsBackup.I2SCTL = i2sInstance[i]->I2SCTL;
}
}
break;
default:
break;
}
}
/**
\fn static void i2sExitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore after exit from sleep.
After recovering from SLPMAN_SLEEP1_STATE, I2S hareware is repowered, we restore user's configurations
by aidding of the stored registers.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void i2sExitLpStateRestore(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < I2S_INSTANCE_NUM; i++)
{
if(i2sDataBase[i].isInited == true)
{
GPR_clockEnable(i2sClk[i*2]);
GPR_clockEnable(i2sClk[i*2 + 1]);
i2sInstance[i]->DFMT = i2sDataBase[i].regsBackup.DFMT;
i2sInstance[i]->SLOTCTL = i2sDataBase[i].regsBackup.SLOTCTL;
i2sInstance[i]->CLKCTL = i2sDataBase[i].regsBackup.CLKCTL;
i2sInstance[i]->DMACTL = i2sDataBase[i].regsBackup.DMACTL;
i2sInstance[i]->INTCTL = i2sDataBase[i].regsBackup.INTCTL;
i2sInstance[i]->TIMEOUTCTL = i2sDataBase[i].regsBackup.TIMEOUTCTL;
i2sInstance[i]->STAS = i2sDataBase[i].regsBackup.STAS;
i2sInstance[i]->I2SCTL = i2sDataBase[i].regsBackup.I2SCTL;
}
}
break;
default:
break;
}
}
#define LOCK_SLEEP(instance) \
do \
{ \
i2sWorkingStats |= (1U << instance); \
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_ACTIVE_STATE); \
} \
while(0)
#define CHECK_TO_UNLOCK_SLEEP(instance) \
do \
{ \
i2sWorkingStats &= ~(1U << instance); \
if(i2sWorkingStats == 0) \
slpManDrvVoteSleep(SLP_VOTE_I2S, SLP_SLP1_STATE); \
} \
while(0)
#endif
static uint32_t i2sGetInstanceNum(i2sResources_t *i2s)
{
return ((uint32_t)i2s->reg - (uint32_t)I2S0) >> 12U;
}
int32_t i2sInit(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent, i2sResources_t *i2s)
{
int32_t returnCode;
PadConfig_t config;
#ifdef PM_FEATURE_ENABLE
uint32_t instance = i2sGetInstanceNum(i2s);
i2sDataBase[instance].isInited = true;
#endif
// Initialize I2S PINS
PAD_getDefaultConfig(&config);
config.mux = i2s->pins.mclk->funcNum;
PAD_setPinConfig(i2s->pins.mclk->pinNum, &config);
config.mux = i2s->pins.bclk->funcNum;
PAD_setPinConfig(i2s->pins.bclk->pinNum, &config);
config.mux = i2s->pins.lrck->funcNum;
PAD_setPinConfig(i2s->pins.lrck->pinNum, &config);
config.mux = i2s->pins.din->funcNum;
PAD_setPinConfig(i2s->pins.din->pinNum, &config);
config.mux = i2s->pins.dout->funcNum;
PAD_setPinConfig(i2s->pins.dout->pinNum, &config);
// Initialize I2S run-time resources
i2s->info->txCbEvent = txCbEvent;
i2s->info->rxCbEvent = rxCbEvent;
// Configure DMA if necessary
if (i2s->dma)
{
// Tx config
DMA_init(i2s->dma->txInstance);
returnCode = DMA_openChannel(i2s->dma->txInstance);
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
return ARM_DRIVER_ERROR;
else
i2s->dma->txCh = returnCode;
DMA_setChannelRequestSource(i2s->dma->txInstance, i2s->dma->txCh, (DmaRequestSource_e)i2s->dma->txReq);
DMA_rigisterChannelCallback(i2s->dma->txInstance, i2s->dma->txCh, i2s->dma->txCb);
// Rx config
DMA_init(i2s->dma->rxInstance);
returnCode = DMA_openChannel(i2s->dma->rxInstance);
if (returnCode == ARM_DMA_ERROR_CHANNEL_ALLOC)
return ARM_DRIVER_ERROR;
else
i2s->dma->rxCh = returnCode;
DMA_setChannelRequestSource(i2s->dma->rxInstance, i2s->dma->rxCh, (DmaRequestSource_e)i2s->dma->rxReq);
DMA_rigisterChannelCallback(i2s->dma->rxInstance, i2s->dma->rxCh, i2s->dma->rxCb);
}
#ifdef PM_FEATURE_ENABLE
i2sInitCnt++;
if(i2sInitCnt == 1U)
{
i2sWorkingStats = 0;
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE, i2sEnterLpStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE, i2sExitLpStateRestore, NULL);
}
#endif
return ARM_DRIVER_OK;
}
int32_t i2sDeInit(i2sResources_t *i2s)
{
#ifdef PM_FEATURE_ENABLE
uint32_t instance = i2sGetInstanceNum(i2s);
i2sDataBase[instance].isInited = false;
i2sInitCnt--;
if(i2sInitCnt == 0)
{
i2sWorkingStats = 0;
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_I2S_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_I2S_MODULE);
}
#endif
return ARM_DRIVER_OK;
}
int32_t i2sPowerCtrl(i2sPowerState_e state, i2sResources_t *i2s)
{
uint32_t instance = i2sGetInstanceNum(i2s);
switch (state)
{
// when need to enter sleep, do not call this api. PMU will manage all the clocks by default.
case I2S_POWER_OFF:
if(i2s->dma)
{
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, false);
}
// Reset register values
if (instance == 0)
{
CLOCK_setClockSrc(FCLK_I2S0, FCLK_I2S0_SEL_26M);
GPR_swReset(RST_PCLK_I2S0);
}
else
{
CLOCK_setClockSrc(FCLK_I2S1, FCLK_I2S1_SEL_26M);
GPR_swReset(RST_PCLK_I2S1);
}
// Disable I2S clock
CLOCK_clockDisable(i2sClk[instance*2]);
CLOCK_clockDisable(i2sClk[instance*2+1]);
break;
case I2S_POWER_FULL:
// Enable I2S clock
CLOCK_clockEnable(i2sClk[instance*2]); // pclk
CLOCK_clockEnable(i2sClk[instance*2+1]); // fclk
GPR_swReset(i2sRstClk[instance*2]); // pclk
GPR_swReset(i2sRstClk[instance*2+1]); // fclk
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
int32_t i2sSend(const void *data, uint32_t chunkNum, i2sResources_t *i2s)
{
uint32_t instance = i2sGetInstanceNum(i2s);
if ((data == NULL) || (chunkNum == 0))
return ARM_DRIVER_ERROR_PARAMETER;
// dma mode
if(i2s->dma)
{
#ifdef PM_FEATURE_ENABLE
LOCK_SLEEP(instance);
#endif
// Configure tx DMA and start it
g_dmaTxConfig.sourceAddress = (void *)data;
g_dmaTxConfig.targetAddress = (void *)&(i2sInstance[instance]->TFIFO);
g_dmaTxConfig.totalLength = chunkNum;
DMA_buildDescriptorChain(i2s->dma->txDescriptor, &g_dmaTxConfig, I2S_DMA_TX_DESCRIPTOR_CHAIN_NUM, true);
DMA_loadChannelDescriptorAndRun(i2s->dma->txInstance, i2s->dma->txCh, i2s->dma->txDescriptor);
}
// polling mode
else
{
for (int i = 0; i < chunkNum; i++)
{
// Flow control. Make sure TX have empty fifo
while (((16 - (i2s->reg->STAS & I2S_STATS_CTRL_TX_FIFO_LEVEL_Msk))
>> I2S_STATS_CTRL_TX_FIFO_LEVEL_Pos) == 0){};
i2s->reg->TFIFO = *(uint32_t*)data;
}
}
return ARM_DRIVER_OK;
}
int32_t i2sRecv(void *data, uint32_t chunkNum, i2sResources_t *i2s)
{
uint32_t instance = i2sGetInstanceNum(i2s);;
if ((data == NULL) || (chunkNum == 0))
return ARM_DRIVER_ERROR_PARAMETER;
// dma mode
if(i2s->dma)
{
#ifdef PM_FEATURE_ENABLE
LOCK_SLEEP(instance);
#endif
// Configure rx DMA and start it
g_dmaRxConfig.sourceAddress = (void *)&(i2sInstance[instance]->RFIFO);
g_dmaRxConfig.targetAddress = (void *)data;
g_dmaRxConfig.totalLength = chunkNum;
DMA_buildDescriptorChain(i2s->dma->rxDescriptor, &g_dmaRxConfig, I2S_DMA_RX_DESCRIPTOR_CHAIN_NUM, true);
DMA_loadChannelDescriptorAndRun(i2s->dma->rxInstance, i2s->dma->rxCh, i2s->dma->rxDescriptor);
}
// polling mode
else
{
for (int i = 0; i < chunkNum; i++)
{
while (((i2s->reg->STAS >> I2S_STATS_CTRL_RX_DAT_RDY_Pos) & 0x1) == 0); // Wait until RxFifo have data
*((uint32_t*)data + i) = i2s->reg->RFIFO;
}
}
return ARM_DRIVER_OK;
}
/**
\fn static int32_t i2sSetBusSpeed(uint32_t bps, i2sResources_t *i2s)
\brief Set bus speed
\param[in] bps bus speed to set
\param[in] spi Pointer to SPI resources
\return \ref execution_status
*/
static int32_t i2sSetSampleRate(uint32_t bps, i2sResources_t *i2s, i2sRole_e i2sRole)
{
uint32_t instance = i2sGetInstanceNum(i2s);
if (instance == 0) // i2s0
{
CLOCK_clockEnable(FCLK_I2S0);
}
else // i2s1
{
CLOCK_clockEnable(FCLK_I2S1);
}
CLOCK_setClockSrc(CLK_CC, CLK_CC_SEL_204M); // Core clk selects 204M
if (instance == 0) // i2s0
{
CLOCK_fracDivOutCLkEnable(FRACDIV0_OUT0); // Fracdiv0 out0 enable
CLOCK_setMclkSrc(MCLK0, MCLK_SRC_FRACDIV0_OUT0); // Choose Fracdiv0 out0 as MClk source
CLOCK_mclkEnable(MCLK0); // Mclk enable
CLOCK_setFracDivOutClkDiv(FRACDIV0_OUT0, 4); // First step to generate MClk clock. 4 div, from 408M -> 102M
// need to add gpr api for fracdiv
int sampleRateIdx;
for (sampleRateIdx = 0; sampleRateIdx < sizeof(i2sSampleRateTbl) / sizeof(i2sSampleRateTbl[0]); sampleRateIdx++)
{
if (bps == i2sSampleRateTbl[sampleRateIdx][0])
{
// Fracdiv clk selects 408M and set frac and integer clk
FracDivConfig_t fracdivCfg;
memset(&fracdivCfg, 0, sizeof(FracDivConfig_t));
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
fracdivCfg.fracDiv0DivRatioInteger = i2sSampleRateTbl[sampleRateIdx][3];
fracdivCfg.fracDiv0DivRatioFrac = i2sSampleRateTbl[sampleRateIdx][2];
CLOCK_setFracDivConfig(&fracdivCfg); // Second step to generate MClk
}
}
}
else // i2s1
{
CLOCK_fracDivOutCLkEnable(FRACDIV1_OUT0); // Fracdiv1 out0 enable
CLOCK_setMclkSrc(MCLK1, MCLK_SRC_FRACDIV1_OUT0); // Choose Fracdiv1 out0 as MClk source
CLOCK_mclkEnable(MCLK1); // Mclk enable
CLOCK_setFracDivOutClkDiv(FRACDIV1_OUT0, 4); // First step to generate MClk clock. 4 div, from 408M -> 102M
// need to add gpr api for fracdiv
int sampleRateIdx;
for (sampleRateIdx = 0; sampleRateIdx < sizeof(i2sSampleRateTbl) / sizeof(i2sSampleRateTbl[0]); sampleRateIdx++)
{
if (bps == i2sSampleRateTbl[sampleRateIdx][0])
{
// Fracdiv clk selects 408M and set frac and integer clk
FracDivConfig_t fracdivCfg;
memset(&fracdivCfg, 0, sizeof(FracDivConfig_t));
fracdivCfg.source = FRACDIC_ROOT_CLK_408M;
fracdivCfg.fracDiv1DivRatioInteger = i2sSampleRateTbl[sampleRateIdx][3];
fracdivCfg.fracDiv1DivRatioFrac = i2sSampleRateTbl[sampleRateIdx][2];
CLOCK_setFracDivConfig(&fracdivCfg); // Second step to generate MClk
}
}
}
if (instance == 0)
{
// I2S master mode need to genetate LRCLK by MCU
if (i2sRole == CODEC_SLAVE_MODE) // I2S controller act as master, codec is slave
{
CLOCK_fracDivOutCLkEnable(FRACDIV0_OUT1); // Enable fracdiv0 out1
CLOCK_setBclkSrc(BCLK0, BCLK_SRC_FRACDIV0_OUT1); // Use fracdiv0 out1 to generate bclk
CLOCK_setFracDivOutClkDiv(FRACDIV0_OUT1, 8); // First step to generate BClk clock. 8 div, from 408M->51M
CLOCK_setBclkDiv(BCLK0, 4); // Second step to generate BClk clock. Bclk enable and divide by 4(256fs)
CLOCK_bclkEnable(BCLK0); // Enable bclk
}
}
else
{
// I2S master mode need to genetate LRCLK by MCU
if (i2sRole == CODEC_SLAVE_MODE) // I2S controller act as master, codec is slave
{
CLOCK_fracDivOutCLkEnable(FRACDIV1_OUT1); // Enable fracdiv1 out1
CLOCK_setBclkSrc(BCLK1, BCLK_SRC_FRACDIV1_OUT1); // Use fracdiv1 out1 to generate bclk
CLOCK_setFracDivOutClkDiv(FRACDIV1_OUT1, 8); // First step to generate BClk clock. 8 div, from 408M->51M
CLOCK_setBclkDiv(BCLK1, 4); // Second step to generate BClk clock. Bclk enable and divide by 4(256fs)
CLOCK_bclkEnable(BCLK1); // Enable bclk
}
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t i2sControl(uint32_t control, uint32_t arg, i2sRes_t *i2s)
\brief Control I2S Interface.
\param[in] control Operation
\param[in] arg Argument of operation (optional)
\param[in] i2s Pointer to I2S resources
\return common \ref execution_status and driver specific \ref spi_execution_status
*/
int32_t i2sControl(uint32_t control, uint32_t arg, i2sResources_t *i2s)
{
uint32_t instance = i2sGetInstanceNum(i2s);
switch(control & 0xFFFF)
{
// Set transport abort
case I2S_CTRL_TRANSABORT:
{
// If DMA mode, disable DMA channel
if(i2s->dma)
{
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, true);
}
break;
}
case I2S_CTRL_SET_TOTAL_NUM:
{
i2s->info->totalNum = arg;
}
// Set Bus Speed in bps; arg = value
case I2S_CTRL_SAMPLE_RATE_SLAVE:
{
if(i2sSetSampleRate(arg, i2s, CODEC_MASTER_MODE) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
break;
}
case I2S_CTRL_SAMPLE_RATE_MASTER:
{
if(i2sSetSampleRate(arg, i2s, CODEC_SLAVE_MODE) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
break;
}
// Set Data Format
case I2S_CTRL_DATA_FORMAT:
{
memcpy((void*)&(i2sInstance[instance]->DFMT), &i2sDataFmt, sizeof(i2sDataFmt_t));
break;
}
// Set Slot
case I2S_CTRL_SLOT_CTRL:
{
memcpy((void*)&(i2sInstance[instance]->SLOTCTL), &i2sSlotCtrl, sizeof(i2sSlotCtrl_t));
break;
}
// Set DMA Control
case I2S_CTRL_DMA_CTRL:
{
memcpy((void*)&(i2sInstance[instance]->DMACTL), &i2sDmaCtrl, sizeof(i2sDmaCtrl_t));
break;
}
// Set I2S Control
case I2S_CTRL_I2SCTL:
{
memcpy((void*)&(i2sInstance[instance]->I2SCTL), &i2sCtrl, sizeof(i2sCtrl_t));
break;
}
// Set Frame Info0
case I2S_CTRL_BCLK_FS_CTRL:
{
memcpy((void*)&(i2sInstance[instance]->CLKCTL), &i2sBclkFsCtrl, sizeof(i2sBclkFsCtrl_t));
break;
}
// Start or stop audio play
case I2S_CTRL_START_STOP:
{
#ifdef PM_FEATURE_ENABLE
if (i2sDataBase[instance].mclkHasBeenClosed == true)
{
GPR_mclkEnable(i2sMClk[instance]);
i2sDataBase[instance].mclkHasBeenClosed = false; // already opened MCLK now
}
#endif
i2sInstance[instance]->I2SCTL = arg; // 0: disable i2s; 1: enable send; 2: enable recv; 3: enable send/recv
break;
}
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
void i2sDmaRxEvent(uint32_t event, i2sResources_t *i2s)
{
#ifdef PM_FEATURE_ENABLE
uint32_t instance = i2sGetInstanceNum(i2s);
#endif
switch(event)
{
case DMA_EVENT_END:
//DMA_stopChannel(i2s->dma->rxInstance, i2s->dma->rxCh, true);
//i2s->reg->I2SCTL &= ~I2S_CTL_MODE_Msk;
if(i2s->info->rxCbEvent)
{
i2s->info->rxCbEvent(I2S_EVENT_TRANSFER_COMPLETE, 0);
}
#ifdef PM_FEATURE_ENABLE
CHECK_TO_UNLOCK_SLEEP(instance);
#endif
break;
default:
break;
}
}
void i2sDmaTxEvent(uint32_t event, i2sResources_t *i2s)
{
#ifdef PM_FEATURE_ENABLE
uint32_t instance = i2sGetInstanceNum(i2s);
#endif
switch(event)
{
case DMA_EVENT_END:
#if 0 // If you want to loop the audio, don't stop DMA here
DMA_stopChannel(i2s->dma->txInstance, i2s->dma->txCh, true);
i2s->info->status.busy = 0;
i2s->reg->I2SCTL &= ~I2S_CTL_MODE_Msk;
#endif
if(i2s->info->txCbEvent)
{
i2s->info->txCbEvent(I2S_EVENT_TRANSFER_COMPLETE, i2s->info->totalNum);
}
#ifdef PM_FEATURE_ENABLE
CHECK_TO_UNLOCK_SLEEP(instance);
#endif
break;
default:
break;
}
}
uint32_t i2sGetTotalCnt(i2sResources_t *i2s)
{
return i2s->info->totalNum;
}
#if (RTE_I2S0)
static int32_t i2s0Init(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent)
{
return i2sInit(txCbEvent, rxCbEvent, &i2s0Res);
}
static int32_t i2s0Deinit(void)
{
return i2sDeInit(&i2s0Res);
}
static int32_t i2s0PowerCtrl(i2sPowerState_e state)
{
return i2sPowerCtrl(state, &i2s0Res);
}
static int32_t i2s0Send(void *data, uint32_t num)
{
return i2sSend(data, num, &i2s0Res);
}
static int32_t i2s0Recv(void *data, uint32_t num)
{
return i2sRecv(data, num, &i2s0Res);
}
static int32_t i2s0Ctrl(uint32_t control, uint32_t arg)
{
return i2sControl(control, arg, &i2s0Res);
}
void i2s0DmaTxEvent(uint32_t event)
{
i2sDmaTxEvent(event, &i2s0Res);
}
void i2s0DmaRxEvent(uint32_t event)
{
i2sDmaRxEvent(event, &i2s0Res);
}
uint32_t i2s0GetTotalCnt(void)
{
return i2sGetTotalCnt(&i2s0Res);
}
// I2S0 Driver Control Block
i2sDrvInterface_t i2sDrvInterface0 =
{
i2s0Init,
i2s0Deinit,
i2s0PowerCtrl,
i2s0Send,
i2s0Recv,
i2s0Ctrl,
i2s0GetTotalCnt,
};
#endif
#if (RTE_I2S1)
static int32_t i2s1Init(i2sCbEvent_fn txCbEvent, i2sCbEvent_fn rxCbEvent)
{
return i2sInit(txCbEvent, rxCbEvent, &i2s1Res);
}
static int32_t i2s1Deinit(void)
{
return i2sDeInit(&i2s1Res);
}
static int32_t i2s1PowerCtrl(i2sPowerState_e state)
{
return i2sPowerCtrl(state, &i2s1Res);
}
static int32_t i2s1Send(void *data, uint32_t num)
{
return i2sSend(data, num, &i2s1Res);
}
static int32_t i2s1Recv(void *data, uint32_t num)
{
return i2sRecv(data, num, &i2s1Res);
}
static int32_t i2s1Ctrl(uint32_t control, uint32_t arg)
{
return i2sControl(control, arg, &i2s1Res);
}
uint32_t i2s1GetTotalCnt(void)
{
return i2sGetTotalCnt(&i2s1Res);
}
void i2s1DmaRxEvent(uint32_t event)
{
i2sDmaRxEvent(event, &i2s1Res);
}
void i2s1DmaTxEvent(uint32_t event)
{
i2sDmaTxEvent(event, &i2s1Res);
}
// I2S1 Driver Control Block
i2sDrvInterface_t i2sDrvInterface1 =
{
i2s1Init,
i2s1Deinit,
i2s1PowerCtrl,
i2s1Send,
i2s1Recv,
i2s1Ctrl,
i2s1GetTotalCnt,
};
#endif

View File

@@ -0,0 +1,414 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: kpc_ec616.c
* Description: EC618 kpc driver source file
* History: Rev1.0 2021-07-23
*
****************************************************************************/
#include "kpc.h"
#include "ic.h"
#include "clock.h"
#include "slpman.h"
//#define KPC_DEBUG
/** \brief Internal used data structure */
typedef struct
{
uint8_t isInited; /**< flag indicating intialized or not */
uint8_t scanState; /**< For key release detect */
uint8_t enableAutoRepeat; /**< autorepeat feature is enabled */
uint8_t padding0;
uint32_t keyEnableMask; /**< Bitmap of enabled keys */
uint32_t keyState; /**< Bitmap of key state, 0-release, 1-press */
struct
{
uint32_t repeatCount; /**< counter for autorepeat */
uint8_t delay; /**< autorepeat event delay */
uint8_t period; /**< autorepeat event period */
uint16_t padding1;
} autoRepeat;
struct
{
uint32_t DEBCTL; /**< Debounce Control Register */
uint32_t KPCTL; /**< Keypad Control Register */
uint32_t DICTL; /**< Direct Input Control Register */
uint32_t KPENCTL; /**< Keypad Enable Register */
uint32_t DIENCTL; /**< Direct Input Enable Register */
} configRegisters;
kpc_callback_t eventCallback; /**< Callback function passed in by application */
} KpcDataBase_t;
static KpcDataBase_t gKpcDataBase = {0};
#ifdef PM_FEATURE_ENABLE
/**
\fn void KPC_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Backup KPC configurations before sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void KPC_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
{
switch(state)
{
case SLPMAN_SLEEP1_STATE:
if(gKpcDataBase.isInited == 1)
{
gKpcDataBase.configRegisters.DEBCTL = KPC->DEBCTL;
gKpcDataBase.configRegisters.KPCTL = KPC->KPCTL;
gKpcDataBase.configRegisters.DICTL = KPC->DICTL;
gKpcDataBase.configRegisters.KPENCTL = KPC->KPENCTL;
gKpcDataBase.configRegisters.DIENCTL = KPC->DIENCTL;
}
break;
default:
break;
}
}
/**
\fn void KPC_exitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore KPC configurations after exit from sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void KPC_exitLowPowerStateRestore(void* pdata, slpManLpState state)
{
switch(state)
{
case SLPMAN_SLEEP1_STATE:
if(gKpcDataBase.isInited == 1)
{
KPC->DEBCTL = gKpcDataBase.configRegisters.DEBCTL;
KPC->KPCTL = gKpcDataBase.configRegisters.KPCTL;
KPC->DICTL = gKpcDataBase.configRegisters.DICTL;
KPC->KPENCTL = gKpcDataBase.configRegisters.KPENCTL;
KPC->DIENCTL = gKpcDataBase.configRegisters.DIENCTL;
}
break;
default:
break;
}
}
#endif
static __FORCEINLINE uint32_t KPC_findFirstSet(uint32_t value)
{
return __CLZ(__RBIT(value));
}
/**
construct key enable bitmap
24 20 19 15 14 10 9 5 4 0
+------------------+------------------+------------------+------------------+------------------+
| row 4, col[4:0] | row 3, col[4:0] | row 2, col[4:0] | row 1,col[4:0] | row 0, col[4:0] |
+------------------+------------------+------------------+------------------+------------------+
*/
static void KPC_setKeyMask(uint32_t rowMask, uint32_t colMask, uint32_t* keyEnableMask, uint32_t* rowMsb, uint32_t* rowCounts)
{
uint32_t keyMask = 0;
uint32_t rowIndex = 0;
uint32_t cnt = 0;
// Max 5x5 matrix keypad
rowMask &= 0x1f;
colMask &= 0x1f;
while(rowMask)
{
rowIndex = KPC_findFirstSet(rowMask);
keyMask |= (colMask << (rowIndex * 5));
rowMask &= (rowMask - 1);
cnt++;
}
*keyEnableMask = keyMask;
*rowMsb = rowIndex;
*rowCounts = cnt;
}
static void KPC_eventReport(void)
{
uint32_t lsb, keyScanResult, keyScanResultBackup, changed, report = 0;
KpcReportEvent_t event;
// Get current key scan result
keyScanResult = KPC->KPSTAT & gKpcDataBase.keyEnableMask;
keyScanResultBackup = keyScanResult;
// Find out changed key
changed = keyScanResult ^ gKpcDataBase.keyState;
#ifdef KPC_DEBUG
printf("report: [%x]-[%x]-[%x]\r\n", keyScanResult, gKpcDataBase.keyState, changed);
#endif
// First to handle key release
if(changed)
{
lsb = KPC_findFirstSet(changed);
// Check key released during two consecutive rounds of scan
if((keyScanResultBackup & ( 1 << lsb)) == 0)
{
event.row = lsb / 5;
event.column = lsb % 5;
event.value = KPC_REPORT_KEY_RELEASE;
gKpcDataBase.autoRepeat.repeatCount = 0;
if(gKpcDataBase.eventCallback)
{
gKpcDataBase.eventCallback(event);
}
}
}
// Check key press
if(keyScanResult)
{
lsb = KPC_findFirstSet(keyScanResult);
// repeat key?
if((gKpcDataBase.keyState & (1 << lsb)) && (gKpcDataBase.enableAutoRepeat == 1))
{
gKpcDataBase.autoRepeat.repeatCount++;
if((gKpcDataBase.autoRepeat.repeatCount >= gKpcDataBase.autoRepeat.delay) && ((gKpcDataBase.autoRepeat.repeatCount - gKpcDataBase.autoRepeat.delay) % gKpcDataBase.autoRepeat.period == 0))
{
event.row = lsb / 5;
event.column = lsb % 5;
event.value = KPC_REPORT_KEY_REPEAT;
report = 1;
}
}
else
{
event.row = lsb / 5;
event.column = lsb % 5;
event.value = KPC_REPORT_KEY_PRESS;
gKpcDataBase.autoRepeat.repeatCount = 0;
report = 1;
}
if(gKpcDataBase.eventCallback && report)
{
gKpcDataBase.eventCallback(event);
}
}
// save current result
gKpcDataBase.keyState = keyScanResultBackup;
}
static void KPC_keyPadModeIsr(void)
{
KPC_eventReport();
// If any key is pressed, enable direct input interrupt which works as a periodic timer for key release detect purpose
KPC->DIENCTL = KPC_DIENCTL_ENABLE_Msk;
KPC->KPENCTL = KPC_KPENCTL_ENABLE_Msk;
gKpcDataBase.scanState = 1; // Indicating at least one key is pressed
}
// Enter at the end of one round of scan period
static void KPC_directInputModeIsr(void)
{
KPC->CLRCTL = KPC_CLRCTL_INPUT_INT_CLR_Msk;
// Check if all keys are released
if((KPC->KPSTAT == 0) && (gKpcDataBase.scanState == 2))
{
KPC->DIENCTL = 0;
gKpcDataBase.scanState = 0;
#ifdef KPC_DEBUG
printf("release,%x\r\n", KPC->DISTAT);
#endif
KPC_eventReport();
}
gKpcDataBase.scanState = 2;
}
void KPC_getDefaultConfig(KpcConfig_t *config)
{
ASSERT(config);
config->debounceConfig.debounceClkDivRatio = KPC_DEBOUNCE_CLK_DIV_RATIO_16384;
config->debounceConfig.debounceWidth = KPC_DEBOUNCE_WIDTH_7_CYCLES;
config->validRowMask = KPC_ROW_ALL;
config->validColumnMask = KPC_COLUMN_ALL;
config->scanPolarity = KPC_SCAN_POLARITY_0;
config->scanDivRatio = KPC_SCAN_DIV_RATIO_16;
config->autoRepeat.enable = 1;
config->autoRepeat.delay = 10;
config->autoRepeat.period = 1;
}
int32_t KPC_init(const KpcConfig_t *config, kpc_callback_t callback)
{
ASSERT(config);
uint32_t mask, validRowCounts, msbOfValidRows;
mask = SaveAndSetIRQMask();
// Initialization
if(gKpcDataBase.isInited == 0)
{
CLOCK_setClockSrc(FCLK_KPC, FCLK_KPC_SEL_26M);
CLOCK_clockEnable(FCLK_KPC);
CLOCK_clockEnable(PCLK_KPC);
GPR_swResetModule(RESET_VECTOR_PTR(KPC_RESET_VECTOR));
// enable KPC IRQ
XIC_SetVector(PXIC0_KPC_DIRECT_IRQn, KPC_directInputModeIsr);
XIC_EnableIRQ(PXIC0_KPC_DIRECT_IRQn);
XIC_SetVector(PXIC0_KPC_KEYPAD_IRQn, KPC_keyPadModeIsr);
XIC_EnableIRQ(PXIC0_KPC_KEYPAD_IRQn);
}
else
{
RestoreIRQMask(mask);
return ARM_DRIVER_OK;
}
RestoreIRQMask(mask);
KPC_setKeyMask(config->validRowMask, config->validColumnMask, &gKpcDataBase.keyEnableMask, &msbOfValidRows, &validRowCounts);
if(validRowCounts < 2)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
KPC->DEBCTL = EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_DEPTH, config->debounceConfig.debounceWidth) | \
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO0_THRD, config->debounceConfig.debounceWidth) | \
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO1_THRD, config->debounceConfig.debounceWidth) | \
EIGEN_VAL2FLD(KPC_DEBCTL_DEBOUNCER_TO_MCLK_RATIO, config->debounceConfig.debounceClkDivRatio);
KPC->KPCTL = EIGEN_VAL2FLD(KPC_KPCTL_POLARITY, config->scanPolarity) | \
EIGEN_VAL2FLD(KPC_KPCTL_ROW_VLD_BITMAP, config->validRowMask & 0x1FU) | \
EIGEN_VAL2FLD(KPC_KPCTL_COL_VLD_BITMAP, config->validColumnMask & 0x1FU) | \
EIGEN_VAL2FLD(KPC_KPCTL_SCAN_TO_DEBOUNCE_RATIO, config->scanDivRatio);
// Enable rising/falling edge interrupt of ending row for key release detect
if(config->scanPolarity == KPC_SCAN_POLARITY_0)
{
KPC->DICTL = EIGEN_VAL2FLD(KPC_DICTL_INT_EN, 1 << (msbOfValidRows + 5)) | EIGEN_VAL2FLD(KPC_DICTL_INT_MODE, 0x1);
}
else
{
KPC->DICTL = EIGEN_VAL2FLD(KPC_DICTL_INT_EN, 1 << (msbOfValidRows + 5)) | EIGEN_VAL2FLD(KPC_DICTL_INT_MODE, 0x2);
}
KPC->AUTOCG = KPC_AUTOCG_ENABLE_Msk;
gKpcDataBase.eventCallback = callback;
gKpcDataBase.enableAutoRepeat = config->autoRepeat.enable;
gKpcDataBase.autoRepeat.delay = config->autoRepeat.delay;
gKpcDataBase.autoRepeat.period = config->autoRepeat.period;
#ifdef PM_FEATURE_ENABLE
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_KPC_MODULE, KPC_enterLowPowerStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_KPC_MODULE, KPC_exitLowPowerStateRestore, NULL);
#endif
gKpcDataBase.isInited = 1;
return ARM_DRIVER_OK;
}
void KPC_deInit(void)
{
uint32_t mask = SaveAndSetIRQMask();
if(gKpcDataBase.isInited == 1)
{
KPC_stopScan();
// disable clock
CLOCK_clockDisable(FCLK_KPC);
CLOCK_clockDisable(PCLK_KPC);
XIC_DisableIRQ(PXIC0_KPC_DIRECT_IRQn);
XIC_DisableIRQ(PXIC0_KPC_KEYPAD_IRQn);
XIC_ClearPendingIRQ(PXIC0_KPC_DIRECT_IRQn);
XIC_ClearPendingIRQ(PXIC0_KPC_KEYPAD_IRQn);
#ifdef PM_FEATURE_ENABLE
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_KPC_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_KPC_MODULE);
#endif
gKpcDataBase.isInited = 0;
}
RestoreIRQMask(mask);
}
void KPC_startScan(void)
{
uint32_t mask = SaveAndSetIRQMask();
if(gKpcDataBase.isInited == 1)
{
KPC->KPENCTL = KPC_KPENCTL_ENABLE_Msk;
}
RestoreIRQMask(mask);
}
void KPC_stopScan(void)
{
uint32_t mask = SaveAndSetIRQMask();
if(gKpcDataBase.isInited == 1)
{
KPC->DIENCTL = 0;
KPC->CLRCTL = KPC_CLRCTL_INPUT_INT_CLR_Msk;
KPC->DICTL = 0;
}
RestoreIRQMask(mask);
}

View File

@@ -0,0 +1,420 @@
/****************************************************************************
*
* Copy right: 2020-, Copyrigths of AirM2M Ltd.
* File name: oneWire.c
* Description: EC618 one wire bus driver source file
* History: Rev1.0 2020-12-17
*
****************************************************************************/
#include "ec618.h"
#include "bsp.h"
#include "oneWire.h"
#include "hal_misc.h"
extern void delay_us(uint32_t us);
#if OW_DEBUG_EN
#define OW_DEBUG(...) printf(__VA_ARGS__)
#else
#define OW_DEBUG(...)
#endif
#define OW_IRQ_MODE 1
static volatile OwStats_e owStats = OW_IDLE;
#define OW_PAD_ADDR (17) //(19)->gpio4 (17)->gpio2 (48)->gpio28 (22)->gpio7
#define OW_PAD_FUNC PAD_MUX_ALT4 //PAD_MUX_ALT3 PAD_MUX_ALT4 PAD_MUX_ALT4 PAD_MUX_ALT4
uint8_t *readBuf = NULL;
#if (OW_IRQ_MODE == 1)
void owIrqHandler(void);
#else
int A, B, C, D, E, F, G, H, I, J;
#endif
void owSetMode(OwModeSel_e mode)
{
if (mode == STANDARD)
{
#if (OW_IRQ_MODE == 1)
#if 0
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_SEND_DIV10, 50);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_WAIT_DIV10, 50);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MIN, 15);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MAX_DIV10, 10);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RECO, 2);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_SLOT_DIV10, 7);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_START, 1);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_WRDLY, 14);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RDDLY, 11);
#endif
#else
OW->ECR |= OW_ECR_RXD_MJR_Msk;
A = 2; // 6us
B = 12; // 64us
C = 16; // 60us
D = 1; // 10us
E = 5; // 9us
F = 28; // 55us
G = 0;
H = 120;// 480us
I = 35; // 70us
J = 150;// 410us
#endif
}
else
{
#if (OW_IRQ_MODE == 1)
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_SEND_DIV10, 50);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_WAIT_DIV10, 50);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MIN, 15);
OW->RTCR = EIGEN_VAL2FLD(OW_RTCR_RESET_RDDLY_MAX_DIV10, 10);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RECO, 2);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_SLOT_DIV10, 7);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_START, 1);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_WRDLY, 14);
OW->ATCR = EIGEN_VAL2FLD(OW_ATCR_WRRD_RDDLY, 11);
#else
#endif
}
}
#if (OW_IRQ_MODE != 1)
void write(uint8_t val)
{
if (val == 1)
{
OW->IOR |= OW_IOR_IO_SWOEN_Msk;
OW->IOR |= OW_IOR_IO_SWOUT_Msk;
}
else
{
OW->IOR |= OW_IOR_IO_SWOEN_Msk;
OW->IOR &= ~OW_IOR_IO_SWOUT_Msk;
}
}
uint8_t read()
{
uint8_t retData, rmjData;
OW->IOR &= ~OW_IOR_IO_SWOEN_Msk;
rmjData = EIGEN_FLD2VAL(OW_ECR_RXD_MJR, OW->ECR);
if (rmjData > 0)
{
retData = EIGEN_FLD2VAL(OW_IOR_IO_SWIN_SYNC, OW->IOR);
}
else
{
retData = EIGEN_FLD2VAL(OW_IOR_IO_SWIN, OW->IOR);
}
return retData;
}
#endif
void owInit()
{
GPR_clockEnable(PCLK_ONEW);
// configure onew pins
PadConfig_t padConfig;
PAD_getDefaultConfig(&padConfig);
padConfig.mux = OW_PAD_FUNC;
PAD_setPinConfig(OW_PAD_ADDR, &padConfig);
#if (OW_IRQ_MODE == 1)
OW->IOR &= ~OW_IOR_IO_SWMODE_Msk;
XIC_SetVector(PXIC0_ONEW_IRQn, owIrqHandler);
XIC_EnableIRQ(PXIC0_ONEW_IRQn);
#else
OW->IOR |= OW_IOR_IO_SWMODE_Msk;
#endif
OW->ECR |= OW_ECR_ENABLE_Msk; // enable onewire
}
void owDeInit()
{
#if (OW_IRQ_MODE == 1)
XIC_DisableIRQ(PXIC0_ONEW_IRQn);
#endif
GPR_clockDisable(PCLK_ONEW);
}
#if (OW_IRQ_MODE == 1)
volatile uint32_t irqNo;
volatile uint16_t count = 0;
void owIrqHandler()
{
++count;
irqNo = OW->IIR;
// Disable ONEW IRQ
XIC_DisableIRQ(PXIC0_ONEW_IRQn);
// Clear pending ONEW interrupts
XIC_ClearPendingIRQ(PXIC0_ONEW_IRQn);
if ((OW->IIR & OW_IIR_INT_RESET_PD_Msk) && ((OW->IIR & OW_IIR_INT_RESET_Msk)!=OW_IIR_INT_RESET_Msk))
{
OW->IER &= ~OW_IER_INTEN_RESET_PD_Msk;
owStats |= OW_RESET_SUCCESS;
OW->IIR |= OW_IIR_INT_CLR_Msk;
}
else if ((OW->IIR & OW_IIR_INT_RESET_Msk) && (OW->IIR & OW_IIR_INT_RESET_PD_Msk))
{
if (OW->IIR & OW_IIR_RESET_PD_RES_Msk)
{
owStats |= OW_RESETPD_SUCCESS;
}
else
{
owStats &= ~OW_RESETPD_SUCCESS;
}
OW->IIR |= OW_IIR_INT_CLR_Msk;
OW->IER &= ~OW_IER_INTEN_RESET_PD_Msk;
}
else if (OW->IIR & OW_IIR_INT_WRITE_Msk)
{
if (OW->IIR & OW_IIR_INT_WRITE_Msk)
{
owStats |= OW_WRITE_SUCCESS;
}
else
{
owStats &= ~OW_WRITE_SUCCESS;
}
OW->IIR |= OW_IIR_INT_CLR_Msk;
OW->IER &= ~OW_IER_INTEN_WRITE_Msk;
}
else if (OW->IIR & OW_IIR_INT_READ_Msk)
{
*readBuf = OW->RBR;
if (OW->IIR & OW_IIR_INT_READ_Msk)
{
owStats |= OW_READ_SUCCESS;
}
else
{
owStats &= ~OW_READ_SUCCESS;
}
OW->IIR |= OW_IIR_INT_CLR_Msk;
OW->IER &= ~OW_IER_INTEN_READ_Msk;
}
OW->OCR |= OW_OCR_CMD_FLUSH_Msk;
XIC_EnableIRQ(PXIC0_ONEW_IRQn);
}
#endif
int32_t owReset()
{
#if (OW_IRQ_MODE == 1)
OW->IER |= OW_IER_INTEN_RESET_PD_Msk;
OW->IER |= OW_IER_INTEN_RESET_Msk;
OW->OCR |= OW_OCR_CMD_RESET_Msk;
while ((owStats & OW_RESET_SUCCESS) != OW_RESET_SUCCESS);
owStats &= ~OW_RESET_SUCCESS;
#else
#endif
return OWDRV_OK;
}
int32_t owResetPd()
{
#if (OW_IRQ_MODE == 1)
OW->IER |= OW_IER_INTEN_RESET_Msk;
delay_us(20); // wait until former irq finish
OW->OCR |= OW_OCR_CMD_RESET_Msk;
while ((owStats & OW_RESETPD_SUCCESS) != OW_RESETPD_SUCCESS);
owStats &= ~OW_RESETPD_SUCCESS;
return OWDRV_OK;
#else
delay_us(50);
//owDelay(G);
write(0);
delay_us(H);
write(1);
delay_us(I);
int ret = read();
delay_us(J);
if (ret == 1)
{
owStats |= OW_RESETPD_SUCCESS;
return OWDRV_OK;
}
else
{
owStats &= ~OW_RESETPD_SUCCESS;
return OWDRV_RESETPD_ERR;
}
#endif
}
int32_t owWriteBit(uint8_t data)
{
#if (OW_IRQ_MODE == 1)
OW->DFR &= ~OW_DFR_MODE_BYTE_Msk;
OW->TBR = data;
OW->IER |= OW_IER_INTEN_WRITE_Msk;
OW->OCR |= OW_OCR_CMD_WRITE_Msk;
while ((owStats & OW_WRITE_SUCCESS) != OW_WRITE_SUCCESS);
owStats &= ~OW_WRITE_SUCCESS;
#else
if (data == 1)
{
write(0);
delay_us(A);
write(1);
delay_us(B);
}
else
{
write(0);
delay_us(C);
write(1);
delay_us(D);
}
#endif
return OWDRV_OK;
}
int32_t owReadBit(uint8_t * dataRead)
{
if (dataRead != NULL)
{
readBuf = dataRead;
}
#if (OW_IRQ_MODE == 1)
OW->DFR &= ~OW_DFR_MODE_BYTE_Msk;
OW->IER |= OW_IER_INTEN_READ_Msk;
OW->OCR |= OW_OCR_CMD_READ_Msk;
while ((owStats & OW_READ_SUCCESS) != OW_READ_SUCCESS);
owStats &= ~OW_READ_SUCCESS;
#else
write(0);
delay_us(1);
write(1);
delay_us(2);
*dataRead = read();
delay_us(14);
#endif
return OWDRV_OK;
}
int32_t owWriteByte(uint8_t data)
{
#if (OW_IRQ_MODE == 1)
OW->DFR |= OW_DFR_MODE_BYTE_Msk;
OW->TBR = data;
OW->IER |= OW_IER_INTEN_WRITE_Msk;
OW->OCR |= OW_OCR_CMD_WRITE_Msk;
while ((owStats & OW_WRITE_SUCCESS) != OW_WRITE_SUCCESS);
owStats &= ~OW_WRITE_SUCCESS;
#else
for (int i=0; i<8; i++)
{
owWriteBit(data & 0x01);
data >>= 1;
}
#endif
return OWDRV_OK;
}
int32_t owReadByte(uint8_t * dataRead)
{
if (dataRead != NULL)
{
readBuf = dataRead;
}
#if (OW_IRQ_MODE == 1)
OW->DFR |= OW_DFR_MODE_BYTE_Msk;
OW->IER |= OW_IER_INTEN_READ_Msk;
OW->OCR |= OW_OCR_CMD_READ_Msk;
while ((owStats & OW_READ_SUCCESS) != OW_READ_SUCCESS);
owStats &= ~OW_READ_SUCCESS;
#else
uint8_t result=0;
uint8_t readBitVal[8];
memset(readBitVal, 0, 8);
for (int i=0; i<8; i++)
{
result >>= 1;
owReadBit(readBitVal+i);
if (readBitVal[i] == 1)
{
result |= 0x80;
}
}
*dataRead = result;
#endif
return OWDRV_OK;
}
int32_t owTouchByte(uint8_t data)
{
int32_t result = 0;
for (uint8_t i=0; i<8; i++)
{
result >>= 1;
// if sending a '1' then read a bit, else write a '0'
if (data & 0x01)
{
if (owReadBit(NULL))
{
result |= 0x80;
}
}
else
{
owWriteBit(0);
}
data >>= 1;
}
return result;
}

View File

@@ -0,0 +1,170 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: pad.c
* Description: EC618 pad driver source file
* History: Rev1.0 2018-11-14
*
****************************************************************************/
#include "pad.h"
#include "clock.h"
#include "slpman.h"
#ifdef PM_FEATURE_ENABLE
static uint32_t gPadBackupRegs[PAD_ADDR_MAX_NUM] = {0};
/**
\fn void PAD_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Backup pad configurations before sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void PAD_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
GPR_clockEnable(PCLK_PAD);
for(i = 0; i < PAD_ADDR_MAX_NUM; i++)
{
gPadBackupRegs[i] = PAD->PCR[i];
}
GPR_clockDisable(PCLK_PAD);
break;
default:
break;
}
}
/**
\fn void PAD_exitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore PAD configurations after exit from sleep.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
void PAD_exitLowPowerStateRestore(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
GPR_clockEnable(PCLK_PAD);
for(i = 0; i < PAD_ADDR_MAX_NUM; i++)
{
PAD->PCR[i] = gPadBackupRegs[i];
}
GPR_clockDisable(PCLK_PAD);
break;
default:
break;
}
}
#endif
void PAD_driverInit(void)
{
#ifdef PM_FEATURE_ENABLE
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_PAD_MODULE, PAD_enterLowPowerStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_PAD_MODULE, PAD_exitLowPowerStateRestore, NULL);
#endif
}
void PAD_driverDeInit(void)
{
#ifdef PM_FEATURE_ENABLE
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_PAD_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_PAD_MODULE);
#endif
}
void PAD_getDefaultConfig(PadConfig_t *config)
{
ASSERT(config);
config->mux = PAD_MUX_ALT0;
config->inputBufferEnable = PAD_INPUT_BUFFER_DISABLE;
config->pullSelect = PAD_PULL_AUTO;
config->pullUpEnable = PAD_PULL_UP_DISABLE;
config->pullDownEnable = PAD_PULL_DOWN_DISABLE;
}
void PAD_setPinConfig(uint32_t paddr, const PadConfig_t *config)
{
ASSERT(config);
ASSERT(paddr < PAD_ADDR_MAX_NUM);
CLOCK_clockEnable(PCLK_PAD);
PAD->PCR[paddr] = *((const uint32_t *)config);
CLOCK_clockDisable(PCLK_PAD);
}
void PAD_setPinMux(uint32_t paddr, PadMux_e mux)
{
ASSERT(paddr < PAD_ADDR_MAX_NUM);
CLOCK_clockEnable(PCLK_PAD);
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_MUX_Msk) | EIGEN_VAL2FLD(PAD_PCR_MUX, mux);
CLOCK_clockDisable(PCLK_PAD);
}
void PAD_enablePinInputBuffer(uint32_t paddr, bool enable)
{
ASSERT(paddr < PAD_ADDR_MAX_NUM);
CLOCK_clockEnable(PCLK_PAD);
if (enable == true)
{
PAD->PCR[paddr] |= PAD_PCR_INPUT_BUFFER_ENABLE_Msk;
}
else
{
PAD->PCR[paddr] &= ~PAD_PCR_INPUT_BUFFER_ENABLE_Msk;
}
CLOCK_clockDisable(PCLK_PAD);
}
void PAD_setPinPullConfig(uint32_t paddr, PadPullConfig_e config)
{
ASSERT(paddr < PAD_ADDR_MAX_NUM);
CLOCK_clockEnable(PCLK_PAD);
switch(config)
{
case PAD_INTERNAL_PULL_UP:
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_DOWN_ENABLE_Msk) | PAD_PCR_PULL_UP_ENABLE_Msk | PAD_PCR_PULL_SELECT_Msk;
break;
case PAD_INTERNAL_PULL_DOWN:
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_UP_ENABLE_Msk) | PAD_PCR_PULL_DOWN_ENABLE_Msk | PAD_PCR_PULL_SELECT_Msk;
break;
case PAD_AUTO_PULL:
PAD->PCR[paddr] = (PAD->PCR[paddr] & ~PAD_PCR_PULL_SELECT_Msk);
break;
default:
break;
}
CLOCK_clockDisable(PCLK_PAD);
}

View File

@@ -0,0 +1,509 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: timer.c
* Description: EC618 timer driver source file
* History: Rev1.0 2018-07-18
*
****************************************************************************/
#include "timer.h"
#include "clock.h"
#include "slpman.h"
#include DEBUG_LOG_HEADER_FILE
#define EIGEN_TIMER(n) ((TIMER_TypeDef *) (AP_TIMER0_BASE_ADDR + 0x1000*n))
#ifdef PM_FEATURE_ENABLE
/** \brief Internal used data structure */
typedef struct
{
bool isInited; /**< Whether timer has been initialized */
struct
{
uint32_t TCTLR; /**< Timer Control Register */
uint32_t TIVR; /**< Timer Init Value Register */
uint32_t TMR[3]; /**< Timer Match N Register */
} backupRegisters; /**< Backup registers for low power restore */
} TimerDatabase_t;
static bool gIsTimerDriverInited = false;
static TimerDatabase_t gTimerDataBase[TIMER_INSTANCE_NUM];
#endif
static ClockId_e gTimerClocks[TIMER_INSTANCE_NUM*2] = {PCLK_TIMER0, FCLK_TIMER0,
PCLK_TIMER1, FCLK_TIMER1,
PCLK_TIMER2, FCLK_TIMER2,
PCLK_TIMER3, FCLK_TIMER3,
PCLK_TIMER4, FCLK_TIMER4,
PCLK_TIMER5, FCLK_TIMER5
};
#ifdef PM_FEATURE_ENABLE
/**
\brief Bitmap of TIMER working status,
when all TIMER instances are not working, we can vote to enter to low power state.
*/
static uint32_t gTimerWorkingStatus;
/**
\fn static void TIMER_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Perform necessary preparations before sleep.
After recovering from SLPMAN_SLEEP1_STATE, TIMER hareware is repowered, we backup
some registers here first so that we can restore user's configurations after exit.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void TIMER_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
{
if(gTimerDataBase[i].isInited == true)
{
gTimerDataBase[i].backupRegisters.TCTLR = EIGEN_TIMER(i)->TCTLR;
gTimerDataBase[i].backupRegisters.TIVR = EIGEN_TIMER(i)->TIVR;
gTimerDataBase[i].backupRegisters.TMR[0] = EIGEN_TIMER(i)->TMR[0];
gTimerDataBase[i].backupRegisters.TMR[1] = EIGEN_TIMER(i)->TMR[1];
gTimerDataBase[i].backupRegisters.TMR[2] = EIGEN_TIMER(i)->TMR[2];
}
}
break;
default:
break;
}
}
/**
\fn static void TIMER_exitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore after exit from sleep.
After recovering from SLPMAN_SLEEP1_STATE, TIMER hareware is repowered, we restore user's configurations
by aidding of the stored registers.
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void TIMER_exitLowPowerStateRestore(void* pdata, slpManLpState state)
{
uint32_t i;
switch (state)
{
case SLPMAN_SLEEP1_STATE:
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
{
if(gTimerDataBase[i].isInited == true)
{
GPR_clockEnable(gTimerClocks[i*2]);
GPR_clockEnable(gTimerClocks[i*2+1]);
EIGEN_TIMER(i)->TCTLR = gTimerDataBase[i].backupRegisters.TCTLR;
EIGEN_TIMER(i)->TIVR = gTimerDataBase[i].backupRegisters.TIVR;
EIGEN_TIMER(i)->TMR[0] = gTimerDataBase[i].backupRegisters.TMR[0];
EIGEN_TIMER(i)->TMR[1] = gTimerDataBase[i].backupRegisters.TMR[1];
EIGEN_TIMER(i)->TMR[2] = gTimerDataBase[i].backupRegisters.TMR[2];
}
}
break;
default:
break;
}
}
#endif
void TIMER_driverInit(void)
{
#ifdef PM_FEATURE_ENABLE
uint32_t i;
if(gIsTimerDriverInited == false)
{
for(i = 0; i < TIMER_INSTANCE_NUM; i++)
{
gTimerDataBase[i].isInited = false;
}
gTimerWorkingStatus = 0;
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_TIMER_MODULE, TIMER_enterLowPowerStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_TIMER_MODULE, TIMER_exitLowPowerStateRestore, NULL);
gIsTimerDriverInited = true;
}
#endif
}
void TIMER_getDefaultConfig(TimerConfig_t *config)
{
ASSERT(config);
config->clockSource = TIMER_INTERNAL_CLOCK;
config->reloadOption = TIMER_RELOAD_ON_MATCH1;
config->initValue = 0;
config->match0 = 0x10000 >> 1U;
config->match1 = 0x10000;
config->match2 = 0xFFFFFFFFU;
}
void TIMER_init(uint32_t instance, const TimerConfig_t *config)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
ASSERT(config);
TIMER_driverInit();
#ifdef PM_FEATURE_ENABLE
if(gTimerDataBase[instance].isInited == false)
{
#endif
CLOCK_clockEnable(gTimerClocks[instance*2]);
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
/* Stop timer counter */
EIGEN_TIMER(instance)->TCCR = 0;
EIGEN_TIMER(instance)->TCTLR = EIGEN_VAL2FLD(TIMER_TCTLR_MODE, config->clockSource) | \
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, config->reloadOption);
EIGEN_TIMER(instance)->TIVR = config->initValue;
EIGEN_TIMER(instance)->TMR[0] = config->match0;
EIGEN_TIMER(instance)->TMR[1] = config->match1;
EIGEN_TIMER(instance)->TMR[2] = config->match2;
#ifdef PM_FEATURE_ENABLE
gTimerDataBase[instance].isInited = true;
}
#endif
}
void TIMER_deInit(uint32_t instance)
{
#ifdef PM_FEATURE_ENABLE
if(gTimerDataBase[instance].isInited == true)
{
#endif
CLOCK_clockDisable(gTimerClocks[instance*2]);
CLOCK_clockDisable(gTimerClocks[instance*2+1]);
#ifdef PM_FEATURE_ENABLE
gTimerDataBase[instance].isInited = false;
}
#endif
}
void TIMER_setMatch(uint32_t instance, TimerMatchSelect_t matchNum, uint32_t matchValue)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TMR[matchNum] = matchValue;
}
void TIMER_setInitValue(uint32_t instance, uint32_t initValue)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TIVR = initValue;
}
void TIMER_setReloadOption(uint32_t instance, TimerReloadOption_t option)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR &~ TIMER_TCTLR_MCS_Msk) | EIGEN_VAL2FLD(TIMER_TCTLR_MCS, option);
}
void TIMER_start(uint32_t instance)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
#ifdef PM_FEATURE_ENABLE
if(instance != 5) // timer 5 do not vote sleep
{
uint32_t mask = SaveAndSetIRQMask();
gTimerWorkingStatus |= (1U << instance);
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_ACTIVE_STATE);
RestoreIRQMask(mask);
}
#endif
EIGEN_TIMER(instance)->TCCR = 1U;
}
void TIMER_stop(uint32_t instance)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TCCR = 0;
#ifdef PM_FEATURE_ENABLE
if(instance != 5) // timer 5 do not vote sleep
{
uint32_t mask = SaveAndSetIRQMask();
gTimerWorkingStatus &= ~(1U << instance);
if (gTimerWorkingStatus == 0)
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_SLP1_STATE);
RestoreIRQMask(mask);
}
#endif
}
uint32_t TIMER_getCount(uint32_t instance)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TCLR = TIMER_TCLR_LATCH_Msk;
while((EIGEN_TIMER(instance)->TCLR & TIMER_TCLR_LATCH_Msk) == TIMER_TCLR_LATCH_Msk);
return EIGEN_TIMER(instance)->TCR;
}
int32_t TIMER_setupPwm(uint32_t instance, const TimerPwmConfig_t *config)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
ASSERT(config);
uint32_t period;
CLOCK_clockEnable(gTimerClocks[instance*2]);
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
if(config->srcClock_HZ == 0 || config->pwmFreq_HZ == 0 || config->srcClock_HZ <= config->pwmFreq_HZ)
return ARM_DRIVER_ERROR_PARAMETER;
period = config->srcClock_HZ / config->pwmFreq_HZ;
/* Set PWM period */
EIGEN_TIMER(instance)->TMR[1] = period - 1;
/* Set duty cycle */
if(config->dutyCyclePercent == 0)
{
EIGEN_TIMER(instance)->TMR[0] = period; // if TMR[0] > TMR[1], PWM output keeps low
}
else if(config->dutyCyclePercent == 100)
{
EIGEN_TIMER(instance)->TMR[0] = period - 1; // let TMR[0] == TMR[1]
}
else
{
/*
Note the higher pwm frequency is, the lower reslution of dutyCycle we'll get.
Below calculation may overflow for specific dutyCyclePercent and in such case, TMR[0] > TMR[1], PWM output keeps low
*/
EIGEN_TIMER(instance)->TMR[0] = ((uint64_t)period) * (100U - config->dutyCyclePercent) / 100U - 1;
}
EIGEN_TIMER(instance)->TIVR = 0;
/* Enable PWM out */
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR & ~ TIMER_TCTLR_MCS_Msk) | \
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, 2U) | TIMER_TCTLR_PWMOUT_Msk;
#ifdef PM_FEATURE_ENABLE
gTimerDataBase[instance].isInited = true;
#endif
return ARM_DRIVER_OK;
}
void TIMER_updatePwmDutyCycle(uint32_t instance, uint32_t dutyCyclePercent)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
if(dutyCyclePercent == 0)
{
EIGEN_TIMER(instance)->TMR[0] = EIGEN_TIMER(instance)->TMR[1] + 1; // if TMR[0] > TMR[1], PWM output keeps low
}
else if(dutyCyclePercent >= 100)
{
EIGEN_TIMER(instance)->TMR[0] = EIGEN_TIMER(instance)->TMR[1]; // let TMR[0] == TMR[1]
}
else
{
EIGEN_TIMER(instance)->TMR[0] = ((uint64_t)EIGEN_TIMER(instance)->TMR[1] + 1) * (100U - dutyCyclePercent) / 100U - 1;
}
}
void TIMER_interruptConfig(uint32_t instance, TimerMatchSelect_t match, TimerInterruptConfig_t config)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
uint32_t enableMask, typeMask, registerValue;
enableMask = 1U << (match + TIMER_TCTLR_IE_0_Pos);
typeMask = 1U << (match + TIMER_TCTLR_IT_0_Pos);
registerValue = EIGEN_TIMER(instance)->TCTLR;
switch(config)
{
case TIMER_INTERRUPT_DISABLED:
registerValue &= ~enableMask;
EIGEN_TIMER(instance)->TCTLR = registerValue;
break;
case TIMER_INTERRUPT_LEVEL:
registerValue |= enableMask;
registerValue &= ~typeMask;
EIGEN_TIMER(instance)->TCTLR = registerValue;
break;
case TIMER_INTERRUPT_PULSE:
registerValue |= enableMask;
registerValue |= typeMask;
EIGEN_TIMER(instance)->TCTLR = registerValue;
break;
default:
break;
}
}
TimerInterruptConfig_t TIMER_getInterruptConfig(uint32_t instance, TimerMatchSelect_t match)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
uint32_t enableMask, typeMask, registerValue;
enableMask = 1U << (match + TIMER_TCTLR_IE_0_Pos);
typeMask = 1U << (match + TIMER_TCTLR_IT_0_Pos);
registerValue = EIGEN_TIMER(instance)->TCTLR;
if ((enableMask & registerValue) == 0)
return TIMER_INTERRUPT_DISABLED;
else if ((typeMask & registerValue) == 0)
return TIMER_INTERRUPT_LEVEL;
else
return TIMER_INTERRUPT_PULSE;
}
uint32_t TIMER_getInterruptFlags(uint32_t instance)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
return EIGEN_TIMER(instance)->TSR;
}
void TIMER_clearInterruptFlags(uint32_t instance, uint32_t mask)
{
ASSERT(instance < TIMER_INSTANCE_NUM);
EIGEN_TIMER(instance)->TSR = mask;
}
static uint8_t gNetLightInstance = 0xff;
void TIMER_netlightEnable(uint8_t instance) // call by user in bsp_custom.c
{
gNetLightInstance = instance;
}
/////// Internal use for Netlight Function /////////////////
void TIMER_netlightPWM(uint8_t mode)
{
extern void delay_us(uint32_t us);
uint8_t instance = gNetLightInstance;
static uint8_t curMode;
#ifdef PM_FEATURE_ENABLE
uint32_t mask;
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, TIMER_netlightPWM_1, P_SIG, "Netlight mode=%u Instance=%d",mode, instance);
#endif
if(instance == 0xff)
return;
ASSERT(instance < TIMER_INSTANCE_NUM);
if(curMode == mode) // do nothing if mode not change
return;
EIGEN_TIMER(instance)->TCCR = 0;
if(mode == 0)
{
EIGEN_TIMER(instance)->TMR[0] = 0xFFFFFFFF;
EIGEN_TIMER(instance)->TMR[1] = 0; // TMR[0] > TMR[1], PWM output keeps low
EIGEN_TIMER(instance)->TCCR = 1;
delay_us(10);
EIGEN_TIMER(instance)->TCCR = 0;
#ifdef PM_FEATURE_ENABLE
if(gTimerWorkingStatus & (1U << instance))
{
CLOCK_clockDisable(gTimerClocks[instance*2]);
CLOCK_clockDisable(gTimerClocks[instance*2+1]);
}
mask = SaveAndSetIRQMask();
gTimerWorkingStatus &= ~(1U << instance);
if (gTimerWorkingStatus == 0)
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_SLP1_STATE);
RestoreIRQMask(mask);
#endif
curMode = 0;
return;
}
#ifdef PM_FEATURE_ENABLE
if((gTimerWorkingStatus & (1U << instance)) == 0)
{
CLOCK_clockEnable(gTimerClocks[instance*2]);
CLOCK_clockEnable(gTimerClocks[instance*2+1]);
}
mask = SaveAndSetIRQMask();
gTimerWorkingStatus |= (1U << instance);
slpManDrvVoteSleep(SLP_VOTE_TIMER, SLP_ACTIVE_STATE);
RestoreIRQMask(mask);
#endif
/* Enable PWM out */
EIGEN_TIMER(instance)->TCTLR = (EIGEN_TIMER(instance)->TCTLR & ~ TIMER_TCTLR_MCS_Msk) | \
EIGEN_VAL2FLD(TIMER_TCTLR_MCS, 2U) | TIMER_TCTLR_PWMOUT_Msk;
if(mode == 1) // fast flash: 64ms high and 800ms low
{
EIGEN_TIMER(instance)->TMR[0] = 0x13D61FF;
EIGEN_TIMER(instance)->TMR[1] = 0x156C5FE;
EIGEN_TIMER(instance)->TCCR = 1;
curMode = mode;
}
else if(mode == 2) // slow flash: 64ms high and 2000ms low
{
EIGEN_TIMER(instance)->TMR[0] = 0x31974FF;
EIGEN_TIMER(instance)->TMR[1] = 0x332D8FE;
EIGEN_TIMER(instance)->TCCR = 1;
curMode = mode;
}
else
{
ASSERT(0);
}
}

View File

@@ -0,0 +1,198 @@
/****************************************************************************
*
* Copy right: 2019-, Copyrigths of AirM2M Ltd.
* File name: tls.c
* Description: This driver is part of SCT(Security Top) module, only focus on AES and SHA functions which are
* mostly used in TLS(transport layer security) area.
* History: Rev1.0 2021-12-3
*
****************************************************************************/
#include "tls.h"
static __attribute__((aligned(4))) sctDescCfg_t sctDescCfg;
void sctInit()
{
// open clock
CLOCK_clockEnable(SCT_RMI_HCLK);
GPR_swReset(RST_SCT_RMI_HCLK);
GPR_swReset(RST_SCT_HCLK);
memset(&sctDescCfg, 0, sizeof(sctDescCfg_t));
// enable sct
*(uint32_t *)SCT_ENABLE_REG = 1;
// set memory guard
sctMemGuard_t *sctMemGuard = (sctMemGuard_t*)SCT_MEM_GUARD_REG;
sctMemGuard->hAddr0 = MGR_HIGH_ADDR;
sctMemGuard->lAddr0 = MGR_LOW_ADDR;
sctMemGuard->hAddr1 = MGR_HIGH_ADDR1;
sctMemGuard->lAddr1 = MGR_LOW_ADDR1;
sctMemGuard->hAddr2 = MGR_HIGH_ADDR2;
sctMemGuard->lAddr2 = MGR_LOW_ADDR2;
sctMemGuard->hAddr3 = MGR_HIGH_ADDR3;
sctMemGuard->lAddr3 = MGR_LOW_ADDR3;
// sct common config
sctCfgWord0_t *cfgWord0 = (sctCfgWord0_t*)SCT_COMM_CFG0_REG;
sctCfgWord1_t *cfgWord1 = (sctCfgWord1_t*)SCT_COMM_CFG1_REG;
sctCfgWord0_t word0;
cfgWord0->val = 0;
cfgWord1->descMaxProcTickTime = 0x4fffb;
word0.ahbAcg = 0;
word0.rmiAcg = 1;
word0.chainStartUnilog = 1;
word0.descDoneUnilog = 1;
word0.chainEndUnilog = 1;
word0.errorIntUnilog = 1;
word0.usbEndianInd = 0;
word0.memHighAddrOffset = 0;
cfgWord0->val = word0.val;
}
static uint32_t sctCheckBusy()
{
sctChaState_t *state = (sctChaState_t*)AES_SHA_CH4_STATE_REG;
if (state->chaBeEmpty)
{
return 0;
}
return 1;
}
static int sctTrigger(sctDescCfg_t* sctDescCfg)
{
if (sctCheckBusy())
{
return SCTDRV_BUSY;
}
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
sctCfgWord->chanCfgWord1 = (uint32_t)sctDescCfg;
CLOCK_clockEnable(SCT_HCLK);
sctCfgWord->chanCfgWord5.trigger = 1;
return SCTDRV_OK;
}
static int sctPollDone(uint32_t timeOutCycle)
{
while (timeOutCycle--)
{
delay_us(1);
if (!sctCheckBusy())
{
return SCTDRV_OK;
}
}
return SCTDRV_TIMEOUT;
}
int32_t aesUpdate(aesInfo_t* aesInfo)
{
uint32_t ret = SCTDRV_OK;
sctDescCfg_t* sctDescCfgPtr = &sctDescCfg;
sctDescCfgPtr->u1.aesField.length = aesInfo->length;
sctDescCfgPtr->u1.aesField.dir = aesInfo->aesCtrl.dir;
sctDescCfgPtr->u1.aesField.aesMode = aesInfo->aesCtrl.aesMode;
sctDescCfgPtr->u1.aesField.paddingMode = aesInfo->aesCtrl.paddingMode;
sctDescCfgPtr->u1.aesField.ckLen = aesInfo->aesCtrl.ckLen;
sctDescCfgPtr->u1.aesField.aesCkSel = aesInfo->aesCtrl.aesCkSel;
sctDescCfgPtr->u1.aesField.subType = 0; // aes
sctDescCfgPtr->u1.aesField.type = 5; // default value is 5
sctDescCfgPtr->srcAddr = aesInfo->srcAddr;
sctDescCfgPtr->dstAddr = aesInfo->dstAddr;
if (aesInfo->aesCtrl.aesCkSel == 0) // from memory
{
sctDescCfgPtr->u2.aesCkAddr = aesInfo->aesCkAddr;;
}
if (aesInfo->aesCtrl.aesMode == 1 || aesInfo->aesCtrl.aesMode == 2) // aes cbc, ctr mode
{
sctDescCfgPtr->u3.aesIvAddr = aesInfo->ivAddr;
}
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
chanCfgWord0_t cfgWord0;
cfgWord0.val = 0;
if (aesInfo->aesCtrl.ckBLEndian == 1) // key is big endian
{
cfgWord0.ckBLEndian = 1;
}
if (aesInfo->aesCtrl.aesIvBLEndian == 1) // iv is big endian
{
cfgWord0.aesIvBLEndian = 1;
}
cfgWord0.fifoLen = 1; // only 1 descriptor(aes)
sctCfgWord->chanCfgWord0.val = cfgWord0.val;
ret = sctTrigger(sctDescCfgPtr);
if (ret != SCTDRV_OK)
{
return SCTDRV_BUSY;
}
ret = sctPollDone(50000);
return ret;
}
// if you need to loop call this api, "lastFlag" should be 0 for intermediate steps, and last step it should be 1.
int32_t shaUpdate(shaType_e shaMode, uint32_t srcAddr, uint32_t dstAddr, uint32_t length, uint32_t lastFlag)
{
uint32_t ret = SCTDRV_OK;
// sha input should 64bytes aligned, if not, you need to padding it first
if ((length & 0x3f) != 0)
{
return SCTDRV_PAMERR;
}
sctDescCfg_t* sctDescCfgPtr = &sctDescCfg;
sctDescCfgPtr->srcAddr = srcAddr; // sha input
sctDescCfgPtr->dstAddr = dstAddr; // sha output
sctDescCfgPtr->u1.shaField.length = length; // sha input length, should 64bytes aligned
sctDescCfgPtr->u1.shaField.subType = 1; // 0: aes; 1:sha
sctDescCfgPtr->u1.shaField.shaMode = shaMode;
sctDescCfgPtr->u1.shaField.type = 5; // default value 5
sctDescCfgPtr->u1.shaField.shaBls = 1; // sha output endian. 0: LE; 1: BE
if (lastFlag == 0)
{
sctDescCfgPtr->u1.shaField.rcs = 1; // data is continuous
sctDescCfgPtr->u1.shaField.outEn = 0; // not output
}
else
{
sctDescCfgPtr->u1.shaField.rcs = 0; // data has been the last sector
sctDescCfgPtr->u1.shaField.outEn = 1; // open sha output value
}
sctDescCfgPtr->u3.shaHeadLen.headLen = 0; // no head
sctCfgWord_t* sctCfgWord = (sctCfgWord_t*)AES_SHA_CH4_CFG_REG;
chanCfgWord0_t cfgWord0;
cfgWord0.val = 0;
cfgWord0.fifoLen = 1; // here only 1 descriptor(sha)
sctCfgWord->chanCfgWord0.val = cfgWord0.val;
ret = sctTrigger(sctDescCfgPtr);
if (ret != SCTDRV_OK)
{
return SCTDRV_BUSY;
}
ret = sctPollDone(50000);
return ret;
}

View File

@@ -0,0 +1,442 @@
#include "usbd_clscdc.h"
#include "usbd_clscdc_cust_tp.h"
//#include "func_dbg.h"
#include "string.h"
#include "usbd_macro_def.h"
#include "usbd_func_cconf.h"
#include "usbd_func_cc.h"
#include "usbd_multi_usrcfg_common.h"
const usbd_cdc_desc_custp1_st t_usbd_cdc_desc_custp1 = {
.intf_ctrl_desc = {
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
/* Interface descriptor type */
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
},
.cdc_diep_desc = {
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00 /* bInterval */
},
.cdc_doep_desc = {
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
}
};
uint8_t vcom_func_custp1_desc_ass(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
p_ccinst_cdc_setting->desc_assigned = 0;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
p_ccinst_cdc_setting->p_desc_src = (const uint8_t *)(&t_usbd_cdc_desc_custp1);
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_custp1);
p_ccinst_cdc_setting->desc_assigned = 1;
return usbd_ret_no_err;
}
uint8_t vcom_func_custp1_desc_parse(usb_func_ccinst_st *p_func_ccinst)
{
const uint8_t * p_desc_buf;
uint16_t pos = 0;
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usb_endpoint_descriptor_st * p_endp_d;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
if(p_ccinst_cdc_setting->desc_assigned!=1)
{
return usbd_ret_fail;
}
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
p_ccinst_cdc_setting->desc_parsed = 0;
p_ccinst_cdc_setting->epctrl_valid = 0;
p_ccinst_cdc_setting->epin_valid = 0;
p_ccinst_cdc_setting->epout_valid = 0;
p_ccinst_cdc_setting->interface_cnt = 0;
while(pos < p_ccinst_cdc_setting->desc_src_size)
{
if (p_desc_buf[pos] == 0)
{
ret = usbd_ret_fail;
break;
}
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
{
ret = usbd_ret_fail;
break;
}
switch (p_desc_buf[pos+1])
{
case USB_ENDPOINT_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
{
ret = usbd_ret_fail;
break;
}
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
{
//if (p_endp_d->bEndpointAddress &0x80)
if (p_endp_d == (&t_usbd_cdc_desc_custp1.cdc_diep_desc))
{
p_ccinst_cdc_setting->epin_valid = 1;
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
}
else if (p_endp_d == (&t_usbd_cdc_desc_custp1.cdc_doep_desc))
{
p_ccinst_cdc_setting->epout_valid = 1;
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
}
else
{
ret = usbd_ret_fail;
break;
}
}
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
{
if (p_endp_d->bEndpointAddress &0x80)
{
p_ccinst_cdc_setting->epctrl_valid = 1;
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
}
else
{
ret = usbd_ret_fail;
break;
}
}
else
{
ret = usbd_ret_fail;
break;
}
break;
case USB_INTERFACE_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
{
ret = usbd_ret_fail;
break;
}
p_ccinst_cdc_setting->interface_cnt++;
break;
default:
break;
}
if (ret!=usbd_ret_no_err)
{
break;
}
pos+= p_desc_buf[pos];
}
if ((p_ccinst_cdc_setting->epctrl_valid ==1) ||
(p_ccinst_cdc_setting->epin_valid ==0) ||
(p_ccinst_cdc_setting->epout_valid==0)||
(p_ccinst_cdc_setting->interface_cnt!=1) )
{
ret = usbd_ret_fail;
}
if (ret == 0)
{
p_ccinst_cdc_setting->desc_parsed = 1;
}
return ret;
}
uint8_t vcom_func_custp1_bind(usb_func_ccinst_st *p_func_ccinst,
ccinst_bind_call_data_st *p_bind_call_data)
{
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
if ((p_ccinst_cdc_setting->desc_assigned==0)
|| (p_ccinst_cdc_setting->desc_parsed==0))
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
p_ccinst_cdc_setting->interface_cnt = p_bind_call_data->interface_cnt;
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
p_ccinst_cdc_setting->binded = 1;
return ret;
}
uint8_t vcom_func_custp1_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_custp1_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_custp1_st *)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_custp1_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_custp1_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_custp1_st*)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_custp1_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_custp1_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_custp1_unbind(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp1_2ep))
{
return usbd_ret_fail;
}
#endif
if (p_ccinst_cdc_setting->binded==0)
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->binded = 0;
return usbd_ret_no_err;
}
#if (VCOM_CCINST_SUBTP1_2EP_CNT > 0)
const ccinst_setting_base_st t_vcom_custp1_base_setting =
{
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp1_2ep
};
ccinst_cdc_setting_st t_vcom_custp1_setting_arr[VCOM_CCINST_SUBTP1_2EP_CNT] ={
//[0]
{
.bs_set = t_vcom_custp1_base_setting,
},
#if (VCOM_CCINST_SUBTP1_2EP_CNT >=2)
//[1]
{
.bs_set = t_vcom_custp1_base_setting,
},
#endif
#if (VCOM_CCINST_SUBTP1_2EP_CNT >= 3)
//[2]
{
.bs_set = t_vcom_custp1_base_setting,
},
#endif
};
usb_func_ccinst_st t_vcom_func_custp1_arr[VCOM_CCINST_SUBTP1_2EP_CNT] ={
//[0]
{
.p_cc_setting = &t_vcom_custp1_setting_arr[0],
.func_desc_ass = vcom_func_custp1_desc_ass,
.func_desc_parse = vcom_func_custp1_desc_parse,
.func_bind = vcom_func_custp1_bind,
.func_get_desc = vcom_func_custp1_get_desc,
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
.func_init = vcom_func_custp1_init,
.func_deinit = vcom_func_custp1_deinit,
.func_unbind = vcom_func_custp1_unbind,
},
#if (VCOM_CCINST_SUBTP1_2EP_CNT >=2)
//[1]
{
.p_cc_setting = &t_vcom_custp1_setting_arr[1],
.func_desc_ass = vcom_func_custp1_desc_ass,
.func_desc_parse = vcom_func_custp1_desc_parse,
.func_bind = vcom_func_custp1_bind,
.func_get_desc = vcom_func_custp1_get_desc,
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
.func_init = vcom_func_custp1_init,
.func_deinit = vcom_func_custp1_deinit,
.func_unbind = vcom_func_custp1_unbind,
},
#endif
#if (VCOM_CCINST_SUBTP1_2EP_CNT >= 3)
//[2]
{
.p_cc_setting = &t_vcom_custp1_setting_arr[2],
.func_desc_ass = vcom_func_custp1_desc_ass,
.func_desc_parse = vcom_func_custp1_desc_parse,
.func_bind = vcom_func_custp1_bind,
.func_get_desc = vcom_func_custp1_get_desc,
.func_get_othspd_desc = vcom_func_custp1_get_othspd_desc,
.func_init = vcom_func_custp1_init,
.func_deinit = vcom_func_custp1_deinit,
.func_unbind = vcom_func_custp1_unbind,
},
#endif
};
#endif

View File

@@ -0,0 +1,501 @@
#include "usbd_clscdc.h"
#include "usbd_clscdc_cust_tp.h"
//#include "func_dbg.h"
#include "string.h"
#include "usbd_macro_def.h"
#include "usbd_func_cconf.h"
#include "usbd_func_cc.h"
#include "usbd_multi_usrcfg_common.h"
#define CC_CUSTP2_CMDEP_MPS 16
const usbd_cdc_desc_custp2_st t_usbd_cdc_desc_custp2 = {
.intf_ctrl_desc = {
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
/* Interface descriptor type */
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
},
.cdc_head_desc = {
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
},
.cdc_callmgr_desc = {
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
INVALID_INTF_NUM, /* bDataInterface: 1 */
},
.cdc_acm_desc = {
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
},
.cdc_union_desc = {
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
INVALID_INTF_NUM,//VCOM_INTF_NUM_0, /* bMasterInterface: Communication class interface */
INVALID_INTF_NUM,//VCOM_INTF_NUM_1, /* bSlaveInterface0: Data Class Interface */
},
.cdc_cmd_ep_desc = {
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CC_CUSTP2_CMDEP_MPS), /* wMaxPacketSize: */
HIBYTE(CC_CUSTP2_CMDEP_MPS),
#ifdef USE_USBC_CTRL_HS
0x10, /* bInterval: */
#else
0xFF, /* bInterval: */
#endif /* USE_USBC_CTRL_HS */
},
.cdc_diep_desc = {
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00 /* bInterval */
},
.cdc_doep_desc = {
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
}
};
uint8_t vcom_func_custp2_desc_ass(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
p_ccinst_cdc_setting->desc_assigned = 0;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
p_ccinst_cdc_setting->p_desc_src =(const uint8_t *)(&t_usbd_cdc_desc_custp2);
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_custp2);
p_ccinst_cdc_setting->desc_assigned = 1;
return usbd_ret_no_err;
}
uint8_t vcom_func_custp2_desc_parse(usb_func_ccinst_st *p_func_ccinst)
{
const uint8_t * p_desc_buf;
uint16_t pos = 0;
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usb_endpoint_descriptor_st * p_endp_d;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
if(p_ccinst_cdc_setting->desc_assigned!=1)
{
return usbd_ret_fail;
}
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
p_ccinst_cdc_setting->desc_parsed = 0;
p_ccinst_cdc_setting->epctrl_valid = 0;
p_ccinst_cdc_setting->epin_valid = 0;
p_ccinst_cdc_setting->epout_valid = 0;
p_ccinst_cdc_setting->interface_cnt = 0;
while(pos < p_ccinst_cdc_setting->desc_src_size)
{
if (p_desc_buf[pos] == 0)
{
ret = usbd_ret_fail;
break;
}
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
{
ret = usbd_ret_fail;
break;
}
switch (p_desc_buf[pos+1])
{
case USB_ENDPOINT_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
{
ret = usbd_ret_fail;
break;
}
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
{
//if (p_endp_d->bEndpointAddress &0x80)
if (p_endp_d == (&t_usbd_cdc_desc_custp2.cdc_diep_desc))
{
p_ccinst_cdc_setting->epin_valid = 1;
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
}
else if (p_endp_d == (&t_usbd_cdc_desc_custp2.cdc_doep_desc))
{
p_ccinst_cdc_setting->epout_valid = 1;
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
}
else
{
ret = usbd_ret_fail;
break;
}
}
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
{
if (p_endp_d->bEndpointAddress &0x80)
{
p_ccinst_cdc_setting->epctrl_valid = 1;
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
}
else
{
ret = usbd_ret_fail;
break;
}
}
else
{
ret = usbd_ret_fail;
break;
}
break;
case USB_INTERFACE_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
{
ret = usbd_ret_fail;
break;
}
p_ccinst_cdc_setting->interface_cnt++;
break;
default:
break;
}
if (ret!=usbd_ret_no_err)
{
break;
}
pos+= p_desc_buf[pos];
}
if ((p_ccinst_cdc_setting->epctrl_valid ==0) ||
(p_ccinst_cdc_setting->epin_valid ==0) ||
(p_ccinst_cdc_setting->epout_valid==0)||
(p_ccinst_cdc_setting->interface_cnt!=1) )
{
ret = usbd_ret_fail;
}
if (ret == 0)
{
p_ccinst_cdc_setting->desc_parsed = 1;
}
return ret;
}
uint8_t vcom_func_custp2_bind(usb_func_ccinst_st *p_func_ccinst,
ccinst_bind_call_data_st *p_bind_call_data)
{
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
if ((p_ccinst_cdc_setting->desc_assigned==0)
|| (p_ccinst_cdc_setting->desc_parsed==0))
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->ep_ctrl_num = p_bind_call_data->ep_ctrl_num;
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
p_ccinst_cdc_setting->intf_2nd_idx = p_bind_call_data->intf_2nd_idx;
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
p_ccinst_cdc_setting->binded = 1;
return ret;
}
uint8_t vcom_func_custp2_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_custp2_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_custp2_st *)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_custp2_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_custp2_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_custp2_st*)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
p_usbd_desc_dst->cdc_cmd_ep_desc.bInterval = 0xff;
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_custp2_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_custp2_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_custp2_unbind(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp2_3ep))
{
return usbd_ret_fail;
}
#endif
if (p_ccinst_cdc_setting->binded==0)
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->binded = 0;
return usbd_ret_no_err;
}
#if (VCOM_CCINST_SUBTP2_3EP_CNT > 0)
const ccinst_setting_base_st t_vcom_custp2_base_setting =
{
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp2_3ep
};
ccinst_cdc_setting_st t_vcom_custp2_setting_arr[VCOM_CCINST_SUBTP2_3EP_CNT] ={
//[0]
{
.bs_set = t_vcom_custp2_base_setting,
},
#if (VCOM_CCINST_SUBTP2_3EP_CNT >=2)
//[1]
{
.bs_set = t_vcom_custp2_base_setting,
},
#endif
#if (VCOM_CCINST_SUBTP2_3EP_CNT >= 3)
//[2]
{
.bs_set = t_vcom_custp2_base_setting,
},
#endif
};
usb_func_ccinst_st t_vcom_func_custp2_arr[VCOM_CCINST_SUBTP2_3EP_CNT] ={
//[0]
{
.p_cc_setting = &t_vcom_custp2_setting_arr[0],
.func_desc_ass = vcom_func_custp2_desc_ass,
.func_desc_parse = vcom_func_custp2_desc_parse,
.func_bind = vcom_func_custp2_bind,
.func_get_desc = vcom_func_custp2_get_desc,
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
.func_init = vcom_func_custp2_init,
.func_deinit = vcom_func_custp2_deinit,
.func_unbind = vcom_func_custp2_unbind,
},
#if (VCOM_CCINST_SUBTP2_3EP_CNT >=2)
//[1]
{
.p_cc_setting = &t_vcom_custp2_setting_arr[1],
.func_desc_ass = vcom_func_custp2_desc_ass,
.func_desc_parse = vcom_func_custp2_desc_parse,
.func_bind = vcom_func_custp2_bind,
.func_get_desc = vcom_func_custp2_get_desc,
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
.func_init = vcom_func_custp2_init,
.func_deinit = vcom_func_custp2_deinit,
.func_unbind = vcom_func_custp2_unbind,
},
#endif
#if (VCOM_CCINST_SUBTP2_3EP_CNT >= 3)
//[2]
{
.p_cc_setting = &t_vcom_custp2_setting_arr[2],
.func_desc_ass = vcom_func_custp2_desc_ass,
.func_desc_parse = vcom_func_custp2_desc_parse,
.func_bind = vcom_func_custp2_bind,
.func_get_desc = vcom_func_custp2_get_desc,
.func_get_othspd_desc = vcom_func_custp2_get_othspd_desc,
.func_init = vcom_func_custp2_init,
.func_deinit = vcom_func_custp2_deinit,
.func_unbind = vcom_func_custp2_unbind,
},
#endif
};
#endif

View File

@@ -0,0 +1,603 @@
#include "usbd_clscdc.h"
#include "usbd_clscdc_cust_tp.h"
#include "string.h"
#include "usbd_macro_def.h"
#include "usbd_func_cconf.h"
#include "usbd_func_cc.h"
#include "usbd_multi_usrcfg_common.h"
typedef struct tag_usbd_cdc_ccinst_desc_inhrnt usbd_cdc_desc_inhrnt_st;
#define CC_INHRNT_CMDEP_MPS 16
#define CCINHRNT_SET_LAST_ERR(err_no) usbd_set_mod_last_err(usb_ccinst_inhrnt_mod, err_no)
const usbd_cdc_desc_inhrnt_st t_usbd_cdc_desc_inhrnt = {
.intf_asso_desc = {
// IAD COM1
0x08, // bLength: Interface Descriptor size
0x0B, // bDescriptorType: IAD
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x02, // iFunction
},
.intf_ctrl_desc = {
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
/* Interface descriptor type */
INVALID_INTF_NUM, //VCOM_INTF_NUM_0, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
},
.cdc_head_desc = {
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
},
.cdc_callmgr_desc = {
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
INVALID_INTF_NUM, /* bDataInterface: 1 */
},
.cdc_acm_desc = {
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
},
.cdc_union_desc = {
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
INVALID_INTF_NUM,//VCOM_INTF_NUM_0, /* bMasterInterface: Communication class interface */
INVALID_INTF_NUM,//VCOM_INTF_NUM_1, /* bSlaveInterface0: Data Class Interface */
},
.cdc_cmd_ep_desc = {
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CC_INHRNT_CMDEP_MPS), /* wMaxPacketSize: */
HIBYTE(CC_INHRNT_CMDEP_MPS),
#ifdef USE_USBC_CTRL_HS
0x10, /* bInterval: */
#else
0xFF, /* bInterval: */
#endif /* USE_USBC_CTRL_HS */
},
.intf_data_desc = {
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
INVALID_INTF_NUM, //VCOM_INTF_NUM_1, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
},
.cdc_diep_desc = {
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00 /* bInterval */
},
.cdc_doep_desc = {
/*Endpoint OUT Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
INVALID_EP_NUM, //CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_DATA_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
}
};
uint8_t vcom_func_inhrnt_desc_ass(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
p_ccinst_cdc_setting->desc_assigned = 0;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
return usbd_ret_fail;
}
#endif
p_ccinst_cdc_setting->p_desc_src =(const uint8_t *)(&t_usbd_cdc_desc_inhrnt);
p_ccinst_cdc_setting->desc_src_size = sizeof(t_usbd_cdc_desc_inhrnt);
p_ccinst_cdc_setting->desc_assigned = 1;
return usbd_ret_no_err;
}
uint8_t vcom_func_inhrnt_desc_parse(usb_func_ccinst_st *p_func_ccinst)
{
const uint8_t * p_desc_buf;
uint16_t pos = 0;
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usb_endpoint_descriptor_st * p_endp_d;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_tpinvalid);
return usbd_ret_fail;
}
#endif
if(p_ccinst_cdc_setting->desc_assigned!=1)
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_ass0);
return usbd_ret_fail;
}
p_desc_buf = p_ccinst_cdc_setting->p_desc_src;
p_ccinst_cdc_setting->desc_parsed = 0;
p_ccinst_cdc_setting->epctrl_valid = 0;
p_ccinst_cdc_setting->epin_valid = 0;
p_ccinst_cdc_setting->epout_valid = 0;
p_ccinst_cdc_setting->interface_cnt = 0;
while(pos < p_ccinst_cdc_setting->desc_src_size)
{
if (p_desc_buf[pos] == 0)
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_len0);
ret = usbd_ret_fail;
break;
}
if ((pos+ p_desc_buf[pos]) > p_ccinst_cdc_setting->desc_src_size)
{
ret = usbd_ret_fail;
CCINHRNT_SET_LAST_ERR(desc_parse_err_len_ovf);
break;
}
switch (p_desc_buf[pos+1])
{
case USB_ENDPOINT_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] != STANDARD_ENDPOINT_DESC_SIZE)
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdesclen);
ret = usbd_ret_fail;
break;
}
p_endp_d = (usb_endpoint_descriptor_st *)(&(p_desc_buf[pos]));
if (p_endp_d->bmAttributes == USBC_CTRL_EP_BULK)
{
//if (p_endp_d->bEndpointAddress &0x80)
if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_diep_desc))
{
p_ccinst_cdc_setting->epin_valid = 1;
p_ccinst_cdc_setting->p_epin_d = p_endp_d;
}
else if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_doep_desc))
{
p_ccinst_cdc_setting->epout_valid = 1;
p_ccinst_cdc_setting->p_epout_d = p_endp_d;
}
else
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdescptr_1);
ret = usbd_ret_fail;
break;
}
}
else if (p_endp_d->bmAttributes == USBC_CTRL_EP_INTR)
{
if (p_endp_d == (&t_usbd_cdc_desc_inhrnt.cdc_cmd_ep_desc))
{
p_ccinst_cdc_setting->epctrl_valid = 1;
p_ccinst_cdc_setting->p_epctrl_d = p_endp_d;
}
else
{
ret = usbd_ret_fail;
CCINHRNT_SET_LAST_ERR(desc_parse_err_epdescptr_2);
break;
}
}
else
{
ret = usbd_ret_fail;
break;
}
break;
case USB_INTERFACE_DESCRIPTOR_TYPE:
if (p_desc_buf[pos] !=STANDARD_INTERFACE_DESC_SIZE)
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_intfdesclen);
ret = usbd_ret_fail;
break;
}
p_ccinst_cdc_setting->interface_cnt++;
break;
default:
break;
}
if (ret!=usbd_ret_no_err)
{
break;
}
pos+= p_desc_buf[pos];
}
if (ret!=usbd_ret_no_err)
{
return ret;
}
if ((p_ccinst_cdc_setting->epctrl_valid ==0) ||
(p_ccinst_cdc_setting->epin_valid ==0) ||
(p_ccinst_cdc_setting->epout_valid==0)||
(p_ccinst_cdc_setting->interface_cnt!=2) )
{
CCINHRNT_SET_LAST_ERR(desc_parse_err_parserslt);
ret = usbd_ret_fail;
}
if (ret == 0)
{
p_ccinst_cdc_setting->desc_parsed = 1;
}
return ret;
}
uint8_t vcom_func_inhrnt_bind(usb_func_ccinst_st *p_func_ccinst,
ccinst_bind_call_data_st *p_bind_call_data)
{
uint8_t ret = usbd_ret_no_err;
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
return usbd_ret_fail;
}
#endif
if ((p_ccinst_cdc_setting->desc_assigned==0)
|| (p_ccinst_cdc_setting->desc_parsed==0))
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->ep_ctrl_num = p_bind_call_data->ep_ctrl_num;
p_ccinst_cdc_setting->ep_datain_num = p_bind_call_data->ep_datain_num;
p_ccinst_cdc_setting->ep_dataout_num = p_bind_call_data->ep_dataout_num;
p_ccinst_cdc_setting->intf_base_idx = p_bind_call_data->intf_base_idx;
p_ccinst_cdc_setting->intf_1st_idx = p_bind_call_data->intf_1st_idx;
p_ccinst_cdc_setting->intf_2nd_idx = p_bind_call_data->intf_2nd_idx;
p_ccinst_cdc_setting->intf_str_id = p_bind_call_data->intf_str_id;
p_ccinst_cdc_setting->binded = 1;
return ret;
}
uint8_t vcom_func_inhrnt_get_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_inhrnt_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_inhrnt_st *)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->cdc_callmgr_desc.bDataInterface = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_asso_desc.bFirstInterface = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->intf_asso_desc.bInterfaceCount = p_ccinst_cdc_setting->interface_cnt;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_data_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->intf_asso_desc.iFunction = p_ccinst_cdc_setting->intf_str_id;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_asso_desc.bFunctionClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_asso_desc.bFunctionSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_asso_desc.bFunctionProtocol = p_desc_call_data->bInterfaceProtocol;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_inhrnt_get_othspd_desc(usb_func_ccinst_st *p_func_ccinst, ccinst_desc_call_data_st*p_desc_call_data)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
usbd_cdc_desc_inhrnt_st *p_usbd_desc_dst;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
return usbd_ret_fail;
}
#endif
if (p_desc_call_data->desc_buff_size < p_ccinst_cdc_setting->desc_src_size)
{
return usbd_ret_fail;
}
if (p_ccinst_cdc_setting->binded == 0)
{
return usbd_ret_fail;
}
p_usbd_desc_dst = (usbd_cdc_desc_inhrnt_st*)(p_desc_call_data->p_desc_buff_ptr);
memcpy(p_usbd_desc_dst, p_ccinst_cdc_setting->p_desc_src, p_ccinst_cdc_setting->desc_src_size);
p_usbd_desc_dst->cdc_cmd_ep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_ctrl_num);
p_usbd_desc_dst->cdc_cmd_ep_desc.bInterval = 0xff;
p_usbd_desc_dst->cdc_diep_desc.bEndpointAddress = EPIN_MARK_DIR(p_ccinst_cdc_setting->ep_datain_num);
p_usbd_desc_dst->cdc_doep_desc.bEndpointAddress = p_ccinst_cdc_setting->ep_dataout_num;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_diep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_High = 0;
p_usbd_desc_dst->cdc_doep_desc.wMaxPacketSize_Low = 0x40;
p_usbd_desc_dst->cdc_callmgr_desc.bDataInterface = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_asso_desc.bFirstInterface = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->intf_asso_desc.bInterfaceCount = p_ccinst_cdc_setting->interface_cnt;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bMasterInterface0 = p_ccinst_cdc_setting->intf_1st_idx;
p_usbd_desc_dst->cdc_union_desc.bSlaveInterface0 = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_data_desc.bInterfaceNumber = p_ccinst_cdc_setting->intf_2nd_idx;
p_usbd_desc_dst->intf_ctrl_desc.iInterface = p_ccinst_cdc_setting->intf_str_id;
p_usbd_desc_dst->intf_asso_desc.iFunction = p_ccinst_cdc_setting->intf_str_id;
if (p_desc_call_data->b_intf_ctrl_desc_upd)
{
p_usbd_desc_dst->intf_asso_desc.bFunctionClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_asso_desc.bFunctionSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_asso_desc.bFunctionProtocol = p_desc_call_data->bInterfaceProtocol;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceClass = p_desc_call_data->bInterfaceClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceSubClass = p_desc_call_data->bInterfaceSubClass;
p_usbd_desc_dst->intf_ctrl_desc.bInterfaceProtocol = p_desc_call_data->bInterfaceProtocol;
}
return usbd_ret_no_err;
}
uint8_t vcom_func_inhrnt_init(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_inhrnt_deinit(usb_func_ccinst_st *p_func_ccinst, uint8_t cfgidx)
{
return usbd_ret_no_err;
}
uint8_t vcom_func_inhrnt_unbind(usb_func_ccinst_st *p_func_ccinst)
{
ccinst_cdc_setting_st* p_ccinst_cdc_setting;
p_ccinst_cdc_setting = p_func_ccinst->p_cc_setting;
#ifdef VCOM_CHK_CCINST_TYPE
if ((p_ccinst_cdc_setting->bs_set.setting_maintp!=ccinst_setting_cdc_vcom_maintp) ||
(p_ccinst_cdc_setting->bs_set.setting_subtp != ccinst_setting_vcom_subtp0_inhrnt))
{
return usbd_ret_fail;
}
#endif
if (p_ccinst_cdc_setting->binded==0)
{
return usbd_ret_fail;
}
p_ccinst_cdc_setting->binded = 0;
return usbd_ret_no_err;
}
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT > 0)
const ccinst_setting_base_st t_vcom_custp0_base_setting =
{
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
};
ccinst_cdc_setting_st t_vcom_custp0_setting_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT] ={
//[0]
{
.bs_set = t_vcom_custp0_base_setting,
},
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >=2)
//[1]
{
.bs_set = t_vcom_custp0_base_setting,
},
#endif
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 3)
//[2]
{
.bs_set = t_vcom_custp0_base_setting,
},
#endif
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 4)
//[2]
{
.bs_set = t_vcom_custp0_base_setting,
},
#endif
};
usb_func_ccinst_st t_vcom_func_custp0_inhrnt_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT] ={
//[0]
{
.p_cc_setting = &t_vcom_custp0_setting_arr[0],
.func_desc_ass = vcom_func_inhrnt_desc_ass,
.func_desc_parse = vcom_func_inhrnt_desc_parse,
.func_bind = vcom_func_inhrnt_bind,
.func_get_desc = vcom_func_inhrnt_get_desc,
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
.func_init = vcom_func_inhrnt_init,
.func_deinit = vcom_func_inhrnt_deinit,
.func_unbind = vcom_func_inhrnt_unbind,
},
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >=2)
//[1]
{
.p_cc_setting = &t_vcom_custp0_setting_arr[1],
.func_desc_ass = vcom_func_inhrnt_desc_ass,
.func_desc_parse = vcom_func_inhrnt_desc_parse,
.func_bind = vcom_func_inhrnt_bind,
.func_get_desc = vcom_func_inhrnt_get_desc,
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
.func_init = vcom_func_inhrnt_init,
.func_deinit = vcom_func_inhrnt_deinit,
.func_unbind = vcom_func_inhrnt_unbind,
},
#endif
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 3)
//[2]
{
.p_cc_setting = &t_vcom_custp0_setting_arr[2],
.func_desc_ass = vcom_func_inhrnt_desc_ass,
.func_desc_parse = vcom_func_inhrnt_desc_parse,
.func_bind = vcom_func_inhrnt_bind,
.func_get_desc = vcom_func_inhrnt_get_desc,
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
.func_init = vcom_func_inhrnt_init,
.func_deinit = vcom_func_inhrnt_deinit,
.func_unbind = vcom_func_inhrnt_unbind,
},
#endif
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT >= 4)
//[3]
{
.p_cc_setting = &t_vcom_custp0_setting_arr[3],
.func_desc_ass = vcom_func_inhrnt_desc_ass,
.func_desc_parse = vcom_func_inhrnt_desc_parse,
.func_bind = vcom_func_inhrnt_bind,
.func_get_desc = vcom_func_inhrnt_get_desc,
.func_get_othspd_desc = vcom_func_inhrnt_get_othspd_desc,
.func_init = vcom_func_inhrnt_init,
.func_deinit = vcom_func_inhrnt_deinit,
.func_unbind = vcom_func_inhrnt_unbind,
},
#endif
};

View File

@@ -0,0 +1,262 @@
#include "bsp.h"
//#include "bsp_custom.h"
#ifndef USB_DRV_SMALL_IMAGE
#include "plat_config.h"
#include DEBUG_LOG_HEADER_FILE
#endif
#include "string.h"
#include "rndis_protocol.h"
#include "usbmst_external.h"
#define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset))
#define CFGBUF ((rndis_config_parameter_t *) INFBUF)
#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
#define PARMVALUELENGTH CFGBUF->ParameterValueLength
#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */
#define MAC_OPT NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \
NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \
NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \
NDIS_MAC_OPTION_NO_LOOPBACK
static const char *rndis_vendor = RNDIS_VENDOR;
const uint32_t OIDSupportedList[] =
{
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_MAC_OPTIONS,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_MAXIMUM_SEND_PACKETS,
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MULTICAST_LIST,
OID_802_3_MAXIMUM_LIST_SIZE,
OID_802_3_MAC_OPTIONS
};
#define OID_LIST_LENGTH (sizeof(OIDSupportedList) / sizeof(*OIDSupportedList))
#define ENC_BUF_SIZE (OID_LIST_LENGTH * 4 + 32)
static const uint8_t station_hwaddr[6] = { RNDIS_HWADDR };
static const uint8_t permanent_hwaddr[6] = { RNDIS_HWADDR };
extern uint32_t connect_status;
//used for malloc buffer
uint32_t RndisGetEncBufSize(void)
{
return ENC_BUF_SIZE;
}
void FuncRndisInitNotify(void)
{
#if (!defined(USB_DRV_SMALL_IMAGE))
usbDevNotifyRndisEvent(NOTIFY_MSG_INIT, NULL);
#endif
}
void FuncRndisHaltNotify(void)
{
#if (!defined(USB_DRV_SMALL_IMAGE))
usbDevNotifyRndisEvent(NOTIFY_MSG_HALT, NULL);
#endif
}
void FuncRndisResetNotify(void)
{
#if (!defined(USB_DRV_SMALL_IMAGE))
usbDevNotifyRndisEvent(NOTIFY_MSG_RESET, NULL);
#endif
}
void RdsProInitalMsgHdl(rndis_generic_msg_t *msgIn)
{
rndis_initialize_cmplt_t *m;
m = ((rndis_initialize_cmplt_t *)msgIn);
/* m->MessageID is same as before */
m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
m->MessageLength = sizeof(rndis_initialize_cmplt_t);
m->MajorVersion = RNDIS_MAJOR_VERSION;
m->MinorVersion = RNDIS_MINOR_VERSION;
m->Status = RNDIS_STATUS_SUCCESS;
m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
m->Medium = RNDIS_MEDIUM_802_3;
m->MaxPacketsPerTransfer = RNDIS_MAX_PACK_PER_XFER;
m->MaxTransferSize = RNDIS_RX_BUFFER_SIZE;
m->PacketAlignmentFactor = 0;
m->AfListOffset = 0;
m->AfListSize = 0;
}
void RdsProQueryCmplt(rndis_query_msg_t *m, int status, const void *data, int size)
{
rndis_query_cmplt_t *c = (rndis_query_cmplt_t *)m;
c->MessageType = REMOTE_NDIS_QUERY_CMPLT;
c->MessageLength = sizeof(rndis_query_cmplt_t) + size;
c->InformationBufferLength = size;
c->InformationBufferOffset = 16;
c->Status = status;
memcpy(c + 1, data, size);
}
void RdsProQueryCmplt32(rndis_query_msg_t *m, int status, uint32_t data)
{
rndis_query_cmplt_t *c = (rndis_query_cmplt_t *)m;
c->MessageType = REMOTE_NDIS_QUERY_CMPLT;
c->MessageLength = sizeof(rndis_query_cmplt_t) + 4;
c->InformationBufferLength = 4;
c->InformationBufferOffset = 16;
c->Status = status;
*(uint32_t *)(c + 1) = data;
}
void RdsProQueryHdl(rndis_query_msg_t *m, rndis_ctrl_data_st *p_ctrl_data)
{
switch (m->Oid)
{
case OID_GEN_SUPPORTED_LIST: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, OIDSupportedList, 4 * OID_LIST_LENGTH); return;
case OID_GEN_VENDOR_DRIVER_VERSION: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0x00001000); return;
case OID_802_3_CURRENT_ADDRESS: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, &station_hwaddr, 6); return;
case OID_802_3_PERMANENT_ADDRESS: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, &permanent_hwaddr, 6); return;
case OID_GEN_MEDIA_SUPPORTED: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
case OID_GEN_MEDIA_IN_USE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
case OID_GEN_PHYSICAL_MEDIUM: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, NDIS_MEDIUM_802_3); return;
case OID_GEN_HARDWARE_STATUS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_GEN_LINK_SPEED: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, RNDIS_LINK_SPEED / 100); return;
case OID_GEN_VENDOR_ID: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0x00FFFFFF); return;
case OID_GEN_VENDOR_DESCRIPTION: RdsProQueryCmplt(m,RNDIS_STATUS_SUCCESS, rndis_vendor, strlen(rndis_vendor) + 1); return;
case OID_GEN_CURRENT_PACKET_FILTER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->oid_packet_filter); return;
case OID_GEN_MAXIMUM_FRAME_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE - ETH_HEADER_SIZE); return;
case OID_GEN_MAXIMUM_TOTAL_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
case OID_GEN_TRANSMIT_BLOCK_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
case OID_GEN_RECEIVE_BLOCK_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, ETH_MAX_PACKET_SIZE); return;
case OID_GEN_MEDIA_CONNECT_STATUS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, connect_status); return;
case OID_GEN_RNDIS_CONFIG_PARAMETER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_802_3_MAXIMUM_LIST_SIZE: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 1); return;
case OID_802_3_MULTICAST_LIST: RdsProQueryCmplt32(m,RNDIS_STATUS_NOT_SUPPORTED, 0); return;
case OID_802_3_MAC_OPTIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_NOT_SUPPORTED, 0); return;
case OID_GEN_MAC_OPTIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_802_3_RCV_ERROR_ALIGNMENT: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_802_3_XMIT_ONE_COLLISION: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_802_3_XMIT_MORE_COLLISIONS: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
case OID_GEN_XMIT_OK: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.txok); return;
case OID_GEN_RCV_OK: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.rxok); return;
case OID_GEN_RCV_ERROR: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.rxbad); return;
case OID_GEN_XMIT_ERROR: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, p_ctrl_data->usb_eth_stat.txbad); return;
case OID_GEN_RCV_NO_BUFFER: RdsProQueryCmplt32(m,RNDIS_STATUS_SUCCESS, 0); return;
default: RdsProQueryCmplt(m,RNDIS_STATUS_FAILURE, NULL, 0); return;
}
}
void RdsProCfgParaHdl(const char *data, int keyoffset, int valoffset, int keylen, int vallen)
{
(void)data;
(void)keyoffset;
(void)valoffset;
(void)keylen;
(void)vallen;
}
void RdsProPktFilter(uint32_t newfilter)
{
(void)newfilter;
}
void RdsProSetMsgHdl(rndis_set_msg_t *msgIn, rndis_ctrl_data_st *p_ctrl_data)
{
rndis_set_cmplt_t *c;
rndis_set_msg_t *m;
rndis_Oid_t oid;
c = (rndis_set_cmplt_t *)msgIn;
m = (rndis_set_msg_t *)msgIn;
oid = m->Oid;
c->MessageType = REMOTE_NDIS_SET_CMPLT;
c->MessageLength = sizeof(rndis_set_cmplt_t);
c->Status = RNDIS_STATUS_SUCCESS;
switch (oid)
{
case OID_GEN_RNDIS_CONFIG_PARAMETER:
{
rndis_config_parameter_t *p;
char *ptr = (char *)m;
ptr += sizeof(rndis_generic_msg_t);
ptr += m->InformationBufferOffset;
p = (rndis_config_parameter_t *)ptr;
RdsProCfgParaHdl(ptr, p->ParameterNameOffset, p->ParameterValueOffset, p->ParameterNameLength, p->ParameterValueLength);
}
break;
case OID_GEN_CURRENT_PACKET_FILTER:
p_ctrl_data->oid_packet_filter = *INFBUF;
if (p_ctrl_data->oid_packet_filter)
{
RdsProPktFilter(p_ctrl_data->oid_packet_filter);
p_ctrl_data->rndis_state = rndis_data_initialized;
}
else
{
p_ctrl_data->rndis_state = rndis_initialized;
}
break;
case OID_GEN_CURRENT_LOOKAHEAD:
break;
case OID_GEN_PROTOCOL_OPTIONS:
break;
case OID_802_3_MULTICAST_LIST:
break;
case OID_PNP_ADD_WAKE_UP_PATTERN:
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
case OID_PNP_ENABLE_WAKE_UP:
default:
c->Status = RNDIS_STATUS_FAILURE;
break;
}
return;
}
void RdsProResetMsgHdl(rndis_reset_cmplt_t *m, rndis_ctrl_data_st *p_ctrl_data)
{
p_ctrl_data->rndis_state = rndis_uninitialized;
m->MessageType = REMOTE_NDIS_RESET_CMPLT;
m->MessageLength = sizeof(rndis_reset_cmplt_t);
m->Status = RNDIS_STATUS_SUCCESS;
m->AddressingReset = 1;
}
void RdsProKeepAliveMsgHdl(rndis_keepalive_cmplt_t *m, uint32_t RequestId, rndis_ctrl_data_st *p_ctrl_data)
{
(void)p_ctrl_data;
m->RequestId = RequestId;
m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
m->MessageLength = sizeof(rndis_keepalive_cmplt_t);
m->Status = RNDIS_STATUS_SUCCESS;
}

View File

@@ -0,0 +1,378 @@
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "usb_portmon.h"
#include "apmu_external.h"
#include "plat_config.h"
#include "string.h"
#include "bsp_custom.h"
#include "slpman.h"
#include "usb_ext_inc.h"
#include DEBUG_LOG_HEADER_FILE
typedef int (*pfn_PadWakeupHook)(uint32_t pad_num);
osEventFlagsId_t vBusEvtFlags = NULL;
#define USB_VBUS_EVT_FLAG 1
//5 for module AirM2M E3 BOARD vbus pad
//#define USB_WKUP_PAD_IDX 5
//for module AirM2M E1 BOARD vbus pad
uint8_t usb_wkup_pad_idx = 1;
#define VBUS_FILTER_MAX_SAMPLE_CNT 10
extern uint8_t usbstack_clear_ctx_stat(void);
extern uint8_t usbstack_ctx_stat_ison(void);
extern uint8_t usbstack_ctx_stat_isoff(void);
extern uint8_t usbstack_get_ctx_stat(void);
extern void usbstack_set_ctx_vbus_mode(uint8_t vbus_mode_en, uint8_t vbus_pad_idx);
extern void usbstack_top_var_clear(void);
extern int RegPadWakeupIntrHook(pfn_PadWakeupHook pfunc);
extern void BSP_UsbDeInit(void);
extern void BSP_UsbInit(void);
int usb_portmon_intr_cb(void);
int Pad1WakeupHook(void);
int PadCmnWakeupHook(uint32_t pad_num);
void usb_portmon_padcfg(void)
{
APmuWakeupPadSettings_t wakeupPadSetting;
wakeupPadSetting.negEdgeEn = true;
wakeupPadSetting.posEdgeEn = true;
wakeupPadSetting.pullDownEn = false;
wakeupPadSetting.pullUpEn = false;
apmuSetWakeupPadCfg(usb_wkup_pad_idx, true, &wakeupPadSetting);
}
uint8_t usb_portmon_wkuppad_level(uint32_t idx);
uint8_t usb_portmon_vbuspad_level(void)
{
return usb_portmon_wkuppad_level(usb_wkup_pad_idx);
}
#define USB_PORTMON_WAIT_INIT_START 10
#define USB_PORTMON_WAIT_FILTER 10
#define USB_PORTMON_WAIT_ALWAYS 0xffffffff
typedef enum
{
usb_portmon_state_none= 0,
usb_portmon_state_filter_reset = 1,
usb_portmon_state_filter_sample = 2,
usb_portmon_state_trigger = 3,
usb_portmon_state_stable = 4,
}usb_portmon_state_type;
uint32_t usb_portmon_stat = usb_portmon_state_none;
usb_portmon_state_type usb_portmon_getstat(void)
{
return usb_portmon_stat;
}
void usb_portmon_setstat(usb_portmon_state_type stat)
{
usb_portmon_stat = stat;
}
uint8_t vbus_val_last = 0;
int usb_portmon_init(void)
{
uint32_t ret;
usbstack_clear_ctx_stat();
vBusEvtFlags = osEventFlagsNew(NULL);
if (vBusEvtFlags== NULL)
{
EC_ASSERT((0), 0, 0, 0);
}
usb_wkup_pad_idx = BSP_UsbGetVBUSWkupPad();
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_init_1, P_WARNING, 1,"usb_wkup_pad_idx %d", usb_wkup_pad_idx);
if (usb_wkup_pad_idx>WAKEUP_PAD_5)
{
EC_ASSERT(0, usb_wkup_pad_idx, WAKEUP_PAD_5, 0);
}
usbstack_top_var_clear();
usbstack_set_ctx_vbus_mode(1,usb_wkup_pad_idx);
NVIC_DisableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
NVIC_ClearPendingIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
ret = RegPadWakeupIntrHook(PadCmnWakeupHook);
EC_ASSERT((ret==0), 0, 0, 0);
usb_portmon_stat = usb_portmon_state_filter_reset;
usb_portmon_padcfg();
NVIC_EnableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
return 0;
}
int usb_portmon_deinit(void){
NVIC_DisableIRQ(PadWakeup0_IRQn+usb_wkup_pad_idx);
if (vBusEvtFlags !=NULL){
osEventFlagsDelete(vBusEvtFlags);
vBusEvtFlags = NULL;
}
usb_portmon_stat = usb_portmon_state_none;
return 0;
}
uint8_t usbpm_vote_handle = 0xff;
void usb_portmon_task(void *arg)
{
uint32_t vbus_evtflag;
uint32_t vbus_filter_sample_cnt = 0;
uint8_t vbus_val_cur = 0;
slpManApplyPlatVoteHandle("usbpm", &usbpm_vote_handle);
slpManPlatVoteDisableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
usb_portmon_init();
uint32_t usb_portmon_wait = USB_PORTMON_WAIT_ALWAYS;
while(1)
{
switch (usb_portmon_getstat())
{
case usb_portmon_state_none:
usb_portmon_setstat(usb_portmon_state_filter_reset);
break;
case usb_portmon_state_filter_reset:
usb_portmon_wait = USB_PORTMON_WAIT_INIT_START;
vbus_evtflag = 0;
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny, usb_portmon_wait);
vbus_val_last = usb_portmon_vbuspad_level();
//reset vbus fileter sample cnt
vbus_filter_sample_cnt = 0;
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
{
//filtered type 3, likely
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, detect evt again continuously in USB_PORTMON_WAIT_FILTER
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_1_1, P_WARNING, 2,"filter reset detect evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
}
else if (vbus_evtflag == osErrorTimeout)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_1_2, P_WARNING, 2,"filter reset (to) evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
}
usb_portmon_setstat(usb_portmon_state_filter_sample);
break;
case usb_portmon_state_filter_sample:
usb_portmon_wait = USB_PORTMON_WAIT_FILTER;
vbus_evtflag = 0;
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny, usb_portmon_wait);
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
{
//filtered type 3, likely
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, detect evt again continuously in USB_PORTMON_WAIT_FILTER
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_1, P_WARNING, 2,"port filtered unstable evt %x, vbus %d", vbus_evtflag, usb_portmon_vbuspad_level() );
usb_portmon_setstat(usb_portmon_state_filter_reset);
break;
}
if (vbus_evtflag == osErrorTimeout)
{
vbus_val_cur = usb_portmon_vbuspad_level();
if (vbus_val_last!=vbus_val_cur)
{
//unlikely
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_2, P_WARNING, 2,"port vbus filter unstable level vbus last %d,vbus cur = %d", vbus_val_last, vbus_val_cur);
usb_portmon_setstat(usb_portmon_state_filter_reset);
vbus_val_last = vbus_val_cur;
break;
}
//anyway update vbus_val_last
vbus_val_last = vbus_val_cur;
//vbus_val_last==vbus_val_cur case
//add vbus fileter sample cnt
vbus_filter_sample_cnt++;
if(vbus_filter_sample_cnt<VBUS_FILTER_MAX_SAMPLE_CNT)
{
//wait for more sample cnt
break;
}
if ((usbstack_ctx_stat_isoff()==1) && (vbus_val_cur ==0))
{
//filtered type 1, unlikely
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, but no pad val change
//no trigger for vbus 0 and usb ctx stat is not on
usb_portmon_setstat(usb_portmon_state_stable);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_3, P_WARNING, 1,"port filtered type2(to) invalid vbus, evt %x, vbus 0 ", vbus_evtflag);
}
else if ((usbstack_ctx_stat_ison()==1) && (vbus_val_cur ==1))
{
//filtered type 2, unlikely
//detect evt in stable state, delay USB_PORTMON_WAIT_FILTER in filter state, but no pad val change
//no trigger for vbus 1 and usb ctx stat is on
usb_portmon_setstat(usb_portmon_state_stable);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_4, P_WARNING, 1,"port filtered type3(to) invalid vbus, evt %x ,vbus 1", vbus_evtflag);
}
else
{
if ((usbstack_ctx_stat_isoff()==0) &&(usbstack_ctx_stat_ison()==0))
{
//anyway pass to trigger state, then cause assert
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_5, P_WARNING, 2,"port vbus trigger warning, ctx stat not valid %x, vbus %d", usbstack_get_ctx_stat(), vbus_val_cur);
}
//most likely
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_2_6, P_INFO, 2,"port vbus trigger, evt %x ,vbus %d", vbus_evtflag, vbus_val_cur);
usb_portmon_setstat(usb_portmon_state_trigger);
}
}
break;
case usb_portmon_state_trigger:
//check the vbus if it is plug out
if (vbus_val_cur==0)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_1, P_WARNING, 0,"BSP_UsbDeInit");
BSP_UsbDeInit();
if(usbstack_ctx_stat_isoff()==0)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_2, P_ERROR, 0,"BSP_UsbDeInit, ctx stat not match");
}
}
else
{
//check the vbus if it is plug in
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_3, P_WARNING, 0,"BSP_UsbInit");
usblpw_clear_lpusbwkup_src();
if (usblpw_retothwk_cur_stg_success()==0)
{
//all other not succ stag anyway set to terminate
usblpw_retothwk_set_terminate_stage();
}
BSP_UsbInit();
if(usbstack_ctx_stat_ison()==0)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_4, P_ERROR, 0,"BSP_UsbInit, ctx stat not match");
}
}
vbus_val_last = usb_portmon_vbuspad_level();
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_3_5, P_WARNING, 2,"port vbus last %d,vbus cur = %d", vbus_val_last, vbus_val_cur);
usb_portmon_setstat(usb_portmon_state_stable);
break;
case usb_portmon_state_stable:
//vote enable sleep when stable state
slpManPlatVoteEnableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
usb_portmon_wait = USB_PORTMON_WAIT_ALWAYS;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_4_1, P_WARNING, 0,"port stable wait evt change");
vbus_evtflag = 0;
vbus_evtflag = osEventFlagsWait (vBusEvtFlags, USB_VBUS_EVT_FLAG, osFlagsWaitAny|osFlagsNoClear, usb_portmon_wait);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_task_4_2, P_WARNING, 1,"port stable detect evt %x", vbus_evtflag);
if (vbus_evtflag&USB_VBUS_EVT_FLAG)
{
usb_portmon_setstat(usb_portmon_state_filter_reset);
}
//vote disable sleep when unstable state
slpManPlatVoteDisableSleep(usbpm_vote_handle, SLP_SLP2_STATE);
break;
}
}
}
int usb_portmon_intr_cb(void)
{
uint32_t wkup_val = usb_portmon_vbuspad_level();
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_portmon_intr_cb_1, P_INFO, 1,"wkup_val:0x%x", wkup_val);
if (usb_portmon_getstat()>usb_portmon_state_none)
{
if (vBusEvtFlags)
{
osEventFlagsSet (vBusEvtFlags, USB_VBUS_EVT_FLAG);
}
}
return 0;
}
int Pad1WakeupHook(void)
{
return usb_portmon_intr_cb();
}
int Pad5WakeupHook(void)
{
return usb_portmon_intr_cb();
}
int PadCmnWakeupHook(uint32_t pad_num)
{
if (pad_num==usb_wkup_pad_idx)
{
switch (usb_wkup_pad_idx)
{
case 1:
Pad1WakeupHook();
break;
case 5:
Pad5WakeupHook();
break;
default:
break;
}
}
return 0;
}
#if (RTE_USB_EN == 1)
#define USBPORTON_TASK_STACK_SIZE (1024)
static uint8_t usb_portmon_task_stack[USBPORTON_TASK_STACK_SIZE];
static StaticTask_t usb_portmon_task_tcb;
//share task stack_ptr
uint8_t *usb_wkmon_portmon_share_stack_ptr(void)
{
return &(usb_portmon_task_stack[0]);
}
uint32_t usb_wkmon_portmon_share_stack_size(void)
{
return USBPORTON_TASK_STACK_SIZE;
}
void usb_portmon_task_init(void)
{
osThreadAttr_t task_attr;
uint8_t * stack_ptr = usb_wkmon_portmon_share_stack_ptr();
uint32_t stack_size = usb_wkmon_portmon_share_stack_size();
memset(&task_attr,0,sizeof(task_attr));
memset(stack_ptr, 0xA5,stack_size);
task_attr.name = "usbpm";
task_attr.stack_mem = stack_ptr;
task_attr.stack_size = stack_size;
task_attr.priority = osPriorityNormal;
task_attr.cb_mem = &usb_portmon_task_tcb;//task control block
task_attr.cb_size = sizeof(StaticTask_t);//size of task control block
osThreadNew(usb_portmon_task, NULL, &task_attr);
}
#endif

View File

@@ -0,0 +1,596 @@
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "usb_wkmon.h"
#include "apmu_external.h"
#include "plat_config.h"
#include "string.h"
#include "bsp_custom.h"
#include "slpman.h"
#include DEBUG_LOG_HEADER_FILE
#include "usb_ext_inc.h"
#include "task.h"
#include "usbd_errinfo.h"
//#include "gpr.h"
#if (USB_WKMON_TASK_EXIST==1)
typedef enum
{
usb_wkmon_state_uninit = 0,
usb_wkmon_state_idle = 1,
usb_wkmon_state_start,
usb_wkmon_state_detecting,
usb_wkmon_state_actv,
usb_wkmon_state_succ ,
usb_wkmon_state_terminate,
}usb_wkmon_state_type;
uint32_t usb_wkmon_stat = usb_wkmon_state_uninit;
void usb_wkmon_setstat(usb_wkmon_state_type stat);
osEventFlagsId_t LPUsbWkStatEvtFlags = NULL;
osEventFlagsId_t LPUsbWkDetEvtFlags = NULL;
#define USB_RETWKUP_STAT_EVT_UPD_FLAG (1UL<0)
#define USB_RETWKUP_STAT_EVT_START_FLAG (1UL<<1)
#define USB_RETWKUP_STAT_EVT_RESET_FLAG (1UL<<2)
#define USB_RETWKUP_DEV_EVT_UPD_FLAG (1UL<0)
#define USB_RETWKUP_DEV_EVT_TRIG_FLAG (1UL<<1)
#define USB_RETWKUP_DEV_EVT_RESET_FLAG (1UL<<2)
typedef int (*pfn_LPUsbWkupHook)(void);
extern int RegLPUSBWkupIntrHook(pfn_LPUsbWkupHook pfunc);
int usb_wkmon_intr_cb(void);
int USBMonLPWkupIRQHook(void);
//#define TEST_LOW_USB_HCLK
int usb_wkmon_pre_init(void)
{
uint32_t ret;
usb_wkmon_stat = usb_wkmon_state_uninit;
#ifdef TEST_LOW_USB_HCLK
GPR_clockEnable(CLK_HF102M);
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_102M);
#endif
LPUsbWkStatEvtFlags = osEventFlagsNew(NULL);
if (LPUsbWkStatEvtFlags== NULL)
{
EC_ASSERT((0), 0, 0, 0);
}
LPUsbWkDetEvtFlags = osEventFlagsNew(NULL);
if (LPUsbWkDetEvtFlags== NULL)
{
EC_ASSERT((0), 0, 0, 0);
}
if (NVIC_GetEnableIRQ(LpusbWakeup_IRQn))
{
//illegal LpusbWakeup_IRQn before start
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
}
ret = RegLPUSBWkupIntrHook(USBMonLPWkupIRQHook);
EC_ASSERT((ret==0), 0, 0, 0);
usb_wkmon_setstat(usb_wkmon_state_idle);
return 0;
}
int usb_wkmon_cmmon_clear(void){
usblpw_wkmon_ll_enter_ctx_clear();
usblpw_wkmon_lpusbwkup_flag_clear();
#ifdef TEST_LOW_USB_HCLK
GPR_clockEnable(CLK_HF102M);
GPR_setClockSrc(CLK_CC, CLK_CC_SEL_102M);
#endif
return 0;
}
int usb_wkmon_deinit(void){
if (LPUsbWkStatEvtFlags !=NULL){
osEventFlagsDelete(LPUsbWkStatEvtFlags);
LPUsbWkStatEvtFlags = NULL;
}
if (LPUsbWkDetEvtFlags !=NULL){
osEventFlagsDelete(LPUsbWkDetEvtFlags);
LPUsbWkDetEvtFlags = NULL;
}
usb_wkmon_setstat(usb_wkmon_state_uninit);
return 0;
}
int usb_wkmon_hibslp2_stat_evt_start(void)
{
uint32_t stat_evtflag;
uint32_t det_evtflag;
if (LPUsbWkDetEvtFlags)
{
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
//any uncleared stat abort
det_evtflag = USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
}
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
return 0;
}
int usb_wkmon_slp1_stat_evt_start(void)
{
uint32_t stat_evtflag;
uint32_t det_evtflag;
uint32_t irqflag;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_1, P_WARNING, 3,"usb_wkmon_stat %d, det evt 0x%x, stat evt 0x%x", usb_wkmon_stat, LPUsbWkDetEvtFlags, LPUsbWkStatEvtFlags);
irqflag = SaveAndSetIRQMask();
switch (usb_wkmon_stat)
{
case usb_wkmon_state_idle:
if (LPUsbWkDetEvtFlags)
{
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
//any uncleared stat abort
det_evtflag = USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
}
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
case usb_wkmon_state_start:
//unlikely here, this stat is sleep disabled
case usb_wkmon_state_actv:
//unlikely , this stat is sleep disabled, deal as all reset
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_2, P_WARNING, 0,"usb_wkmon_stat unlikely");
case usb_wkmon_state_detecting:
//abort detecting and reset to none
if (LPUsbWkDetEvtFlags)
{
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsClear(LPUsbWkDetEvtFlags,det_evtflag);
//any uncleared stat abort
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG;
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
}
//start
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
case usb_wkmon_state_succ:
//start
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG|USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
default:
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_stat);
break;
}
RestoreIRQMask(irqflag);
return 0;
}
int usb_wkmon_slp1_nothwk_evt_reset(void)
{
uint32_t stat_evtflag;
uint32_t det_evtflag;
uint32_t irqflag;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_nothwk_evt_reset_1, P_WARNING, 3,"usb_wkmon_stat %d, det evt 0x%x, stat evt 0x%x", usb_wkmon_stat, LPUsbWkDetEvtFlags, LPUsbWkStatEvtFlags);
irqflag = SaveAndSetIRQMask();
switch (usb_wkmon_stat)
{
case usb_wkmon_state_uninit:
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_uninit, P_WARNING, 0," ");
break;
case usb_wkmon_state_idle:
if (LPUsbWkDetEvtFlags)
{
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsClear(LPUsbWkDetEvtFlags, det_evtflag);
}
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
case usb_wkmon_state_start:
//unlikely here, this stat is sleep disabled
case usb_wkmon_state_actv:
//unlikely , this stat is sleep disabled, deal as all reset
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_slp1_stat_evt_start_2, P_WARNING, 0,"usb_wkmon_stat unlikely");
case usb_wkmon_state_detecting:
//abort detecting and reset to none
if (LPUsbWkDetEvtFlags)
{
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG |USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
osEventFlagsClear(LPUsbWkDetEvtFlags,det_evtflag);
//any uncleared stat abort
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG;
osEventFlagsSet (LPUsbWkDetEvtFlags, det_evtflag);
}
//start
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
case usb_wkmon_state_succ:
//start
if (LPUsbWkStatEvtFlags)
{
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG | USB_RETWKUP_STAT_EVT_START_FLAG|USB_RETWKUP_STAT_EVT_UPD_FLAG;
osEventFlagsClear (LPUsbWkStatEvtFlags, stat_evtflag);
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
osEventFlagsSet (LPUsbWkStatEvtFlags, stat_evtflag);
}
break;
default:
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_stat);
break;
}
RestoreIRQMask(irqflag);
return 0;
}
usb_wkmon_state_type usb_wkmon_getstat(void)
{
return usb_wkmon_stat;
}
void usb_wkmon_setstat(usb_wkmon_state_type stat)
{
usb_wkmon_stat = stat;
}
void BSP_UsbWkIRQLog(void);
//uint8_t BSP_UsbRetOthWkLaterRestOnly(void);
uint8_t usbwkm_vote_handle = 0xff;
//5ms
//#define USBWKM_DET_WAIT_TIME 5
uint8_t usblpw_rd_reg_retwkup_ctxstat(void);
void usb_wkmon_task(void *arg)
{
uint32_t stat_evtflag;
uint32_t det_evtflag;
uint32_t stat_evt_retval;
uint32_t det_evt_retval;
uint32_t irqflag;
uint8_t ret;
uint8_t stage;
usb_wkmon_setstat(usb_wkmon_state_idle);
slpManApplyPlatVoteHandle("usbwk", &usbwkm_vote_handle);
//slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
while(1)
{
switch (usb_wkmon_getstat())
{
case usb_wkmon_state_idle:
stat_evtflag = USB_RETWKUP_STAT_EVT_START_FLAG | USB_RETWKUP_STAT_EVT_UPD_FLAG;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_0, P_INFO, 0,"start");
stat_evt_retval = osEventFlagsWait (LPUsbWkStatEvtFlags, stat_evtflag, osFlagsWaitAny, portMAX_DELAY);
stage = usblpw_retothwk_get_cur_stg();
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_1, P_INFO, 2,"stage 0x%x, stat_evt_retval:0x%x", stage, stat_evt_retval);
if (stat_evt_retval&USB_RETWKUP_STAT_EVT_START_FLAG)
{
if ((usblpw_retothwk_cur_stg_hibslp2_wkmon()==0) &&(usblpw_retothwk_cur_stg_slp1_wkmon()==0))
{
//only enabled from wkmon is legal
//ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_2, P_WARNING, 1,"wkmon stage %d not match", stage);
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
break;
//continue;
}
slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
usb_wkmon_setstat(usb_wkmon_state_start);
break;
}
else if (stat_evt_retval&0x80000000)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_3, P_WARNING, 1,"stat_evt_retval err 0x%x", stat_evt_retval);
}
else
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_none_4, P_WARNING, 1,"stat_evt_retval no proc 0x%x", stat_evt_retval);
}
break;
case usb_wkmon_state_start:
if (NVIC_GetEnableIRQ(LpusbWakeup_IRQn))
{
//illegal LpusbWakeup_IRQn before start
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
break;
}
irqflag = SaveAndSetIRQMask();
//enable here after the wkup irq hook, otherwise the irq may not clear in irq hook
usblpw_enable_lpusbwkup_src();
usblpw_wkmon_lpusbwkup_flag_set();
usb_wkmon_setstat(usb_wkmon_state_detecting);
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
//because no usb drv is active here, so enable
slpManDrvVoteSleep(SLP_VOTE_LPUSB, SLP_SLP1_STATE);
RestoreIRQMask(irqflag);
break;
case usb_wkmon_state_detecting:
det_evt_retval = 0;
det_evtflag = USB_RETWKUP_DEV_EVT_RESET_FLAG | USB_RETWKUP_DEV_EVT_TRIG_FLAG | USB_RETWKUP_DEV_EVT_UPD_FLAG;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_0_0, P_INFO, 0,"usb_wkmon_state_detecting start");
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_0_1, P_INFO, 1,"ctx stat reg %d", usblpw_rd_reg_retwkup_ctxstat());
//may sleep here, current is enable sleep default
det_evt_retval = osEventFlagsWait (LPUsbWkDetEvtFlags, det_evtflag, osFlagsWaitAny, portMAX_DELAY);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_1, P_INFO, 1,"det_evt_retval:0x%x", det_evt_retval);
if (det_evt_retval&USB_RETWKUP_DEV_EVT_TRIG_FLAG)
{
//tirg stat, sleep is disabled by irq hook
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_2, P_WARNING, 0,"detect evt succ");
ret = usblpw_retothwk_wkmon_idle_to_actv_proc();
if (ret !=0)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_3_1, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc fail");
usb_wkmon_setstat(usb_wkmon_state_terminate);
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
//assert here
break;
}
if (usblpw_retothwk_cur_proc_stat_gpwr_umatch())
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_3_2, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc more detecting");
irqflag = SaveAndSetIRQMask();
//enable here after the wkup irq hook, otherwise the irq may not clear in irq hook
usblpw_enable_lpusbwkup_src();
usblpw_wkmon_lpusbwkup_flag_set();
usb_wkmon_setstat(usb_wkmon_state_detecting);
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
//because no usb drv is active here, so enable
slpManDrvVoteSleep(SLP_VOTE_LPUSB, SLP_SLP1_STATE);
RestoreIRQMask(irqflag);
break;
}
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_4, P_WARNING, 0,"usblpw_retothwk_wkmon_idle_to_actv_proc succ");
usb_wkmon_setstat(usb_wkmon_state_actv);
}
else if (det_evt_retval&USB_RETWKUP_DEV_EVT_RESET_FLAG)
{
//must be triggered by sleep1
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_5, P_WARNING, 0,"detecting reset event ");
//unlikely just wait for next trigger, restart
usb_wkmon_setstat(usb_wkmon_state_idle);
}
else if (det_evt_retval == osErrorTimeout)
{
//slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_6, P_WARNING, 0,"detect (to) ");
usb_wkmon_setstat(usb_wkmon_state_detecting);
}
else
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_1_7, P_WARNING, 0,"unknown event ");
//unlikely just wait for next trigger, restart
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
usb_wkmon_setstat(usb_wkmon_state_start);
}
break;
case usb_wkmon_state_actv:
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_0, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc start");
ret = usblpw_retothwk_wkmon_actv_proc();
if (ret != 0)
{
//terminate laterdet or assert
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_1, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc fail");
usb_wkmon_setstat(usb_wkmon_state_terminate);
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
break;
}
if (usblpw_retothwk_cur_stg_success()==0)
{
usb_wkmon_setstat(usb_wkmon_state_terminate);
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usblpw_get_retothwk_proc_stat());
}
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_2_2, P_WARNING, 0,"usblpw_retothwk_wkmon_actv_proc succ");
usblpw_wkmon_lpusbwkup_flag_clear();
usb_wkmon_setstat(usb_wkmon_state_succ);// try next loopo
break;
case usb_wkmon_state_succ:
stat_evtflag = USB_RETWKUP_STAT_EVT_RESET_FLAG;
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_0, P_INFO, 0,"start");
slpManPlatVoteEnableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
stat_evt_retval = osEventFlagsWait (LPUsbWkStatEvtFlags, stat_evtflag, osFlagsWaitAny, portMAX_DELAY);
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_1, P_INFO, 1,"stat_evt_retval:0x%x", stat_evt_retval);
if (stat_evt_retval&USB_RETWKUP_STAT_EVT_RESET_FLAG)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_2, P_WARNING, 0,"stat_evt_retval reset");
usb_wkmon_setstat(usb_wkmon_state_idle);
break;
}
else if (stat_evt_retval&0x80000000)
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_3, P_WARNING, 0,"stat_evt_retval err ");
}
else
{
ECOMM_TRACE(UNILOG_PLA_DRIVER, usb_wkmon_task_state_succ_4, P_WARNING, 0, "stat_evt_retval default proc as reset");
usb_wkmon_setstat(usb_wkmon_state_idle);
}
break;
default:
EC_ASSERT(0, usbd_get_mod_last_err(), usblpw_retothwk_get_cur_stg(), usb_wkmon_getstat());
break;
}
}
}
void BSP_LPUsbWkIRQLog(void)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, BSP_LPUsbWkIRQLog_1, P_VALUE, "othwkup stage %d, proc_stat %d", usblpw_get_retothwk_stage(), usblpw_get_retothwk_proc_stat());
}
int usb_wkmon_intr_cb(void)
{
if ((usblpw_retothwk_cur_stg_hibslp2_wkmon()) || (usblpw_retothwk_cur_stg_slp1_wkmon()))
{
if (usb_wkmon_getstat()==usb_wkmon_state_detecting)
{
//the legal wkmon stat is usb_wkmon_state_detecting for dev event
osEventFlagsSet (LPUsbWkDetEvtFlags, USB_RETWKUP_DEV_EVT_TRIG_FLAG|USB_RETWKUP_DEV_EVT_UPD_FLAG);
NVIC_DisableIRQ(LpusbWakeup_IRQn);
slpManPlatVoteDisableSleep(usbwkm_vote_handle, SLP_SLP1_STATE);
}
else
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_1_0, P_VALUE, "usb_wkmon_stat %d not match, no event sent", usb_wkmon_getstat());
}
if (usblpw_wkmon_ll_enter_ctx_get())
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_1_1, P_VALUE, "chk_abort_ll_inirq, wkmon_lpusbwkup_flag %x", usblpw_wkmon_lpusbwkup_flag_get());
usblpw_enter_wkmon_chk_abort_ll_inirq();
}
}
else if (usblpw_retothwk_cur_stg_none()==0)
{
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usb_wkmon_intr_cb_2, P_VALUE, "unlegal stag");
}
return 0;
}
int USBMonLPWkupIRQHook(void)
{
BSP_LPUsbWkIRQLog();
return usb_wkmon_intr_cb();
}
#define USBWKM_TASK_STACK_SIZE (1024)
//#define USB_WKMON_PRIVATE_STACK
#ifdef USB_WKMON_PRIVATE_STACK
static uint8_t usb_wkmon_task_stack[USBWKM_TASK_STACK_SIZE];
static StaticTask_t usb_wkmon_task_tcb;
uint8_t *usb_wkmon_get_stack_ptr(void)
{
return &(usb_wkmon_task_stack[0]);
}
uint32_t usb_wkmon_get_stack_size(void)
{
return USBWKM_TASK_STACK_SIZE;
}
#else
static StaticTask_t usb_wkmon_task_tcb;
extern uint8_t *usb_wkmon_portmon_share_stack_ptr(void);
extern uint32_t usb_wkmon_portmon_share_stack_size(void);
#endif
void usb_wkmon_task_init(void)
{
osThreadAttr_t task_attr;
uint8_t * stack_ptr = usb_wkmon_portmon_share_stack_ptr();
uint32_t stack_size = usb_wkmon_portmon_share_stack_size();
memset(&task_attr,0,sizeof(task_attr));
memset(stack_ptr, 0xA5,stack_size);
task_attr.name = "usbwkm";
task_attr.stack_mem = stack_ptr;
task_attr.stack_size = stack_size;
task_attr.priority = osPriorityNormal;
task_attr.cb_mem = &usb_wkmon_task_tcb;//task control block
task_attr.cb_size = sizeof(StaticTask_t);//size of task control block
osThreadNew(usb_wkmon_task, NULL, &task_attr);
}

View File

@@ -0,0 +1,993 @@
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "plat_config.h"
#include "string.h"
#include "usbd_clscdc.h"
#include "usbd_func_cc.h"
#include "usbd_multi_usrcfg_common.h"
#ifndef USB_DRV_SMALL_IMAGE
#include "plat_config.h"
#include DEBUG_LOG_HEADER_FILE
#endif
#include "RTE_Device.h"
#define USBD_MULTIDEV_LOAD_FAIL 1
#define EP_REMAP_CUSTOM_CNT 13
#define CUST_DEF_TEST_TYPE1
//#define CUST_DEF_TEST_TYPE3
//#define USBD_EMC_MAC_CONFIG
#ifdef USBD_EMC_MAC_CONFIG
extern uint8_t *ecm_dev_local_string[1];
void update_ecm_mac(void)
{
#ifndef USB_DRV_SMALL_IMAGE
ecm_dev_local_string[0] = (uint8_t*)"2089846a96ab";//update the ecm mac here
#endif
}
#endif
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT>0)
extern usb_func_ccinst_st t_vcom_func_custp0_inhrnt_arr[VCOM_CCINST_SUBTP0_INHERENT_CNT];
#endif
extern usb_func_ccinst_st t_vcom_func_custp1_arr[VCOM_CCINST_SUBTP1_2EP_CNT];
extern usb_func_ccinst_st t_vcom_func_custp2_arr[VCOM_CCINST_SUBTP2_3EP_CNT];
typedef struct {
uint8_t vcom_ccinst_subtp0_inhrnt_cnt;
uint8_t vcom_ccinst_subtp1_2ep_cnt;
uint8_t vcom_ccinst_subtp2_3ep_cnt;
usb_func_ccinst_st *p_vcom_ccinst_subtp0_entry;
usb_func_ccinst_st *p_vcom_ccinst_subtp1_entry;
usb_func_ccinst_st *p_vcom_ccinst_subtp2_entry;
}usbd_multidev_ccinst_res_st;
usbd_multidev_ccinst_res_st t_usbd_multidev_ccinst_res =
{
.vcom_ccinst_subtp0_inhrnt_cnt = VCOM_CCINST_SUBTP0_INHERENT_CNT,
.vcom_ccinst_subtp1_2ep_cnt = VCOM_CCINST_SUBTP1_2EP_CNT,
.vcom_ccinst_subtp2_3ep_cnt = VCOM_CCINST_SUBTP2_3EP_CNT,
#if (VCOM_CCINST_SUBTP0_INHERENT_CNT>0)
.p_vcom_ccinst_subtp0_entry = &(t_vcom_func_custp0_inhrnt_arr[0]),
#endif
#if (VCOM_CCINST_SUBTP1_2EP_CNT >0)
.p_vcom_ccinst_subtp1_entry = &(t_vcom_func_custp1_arr[0]),
#endif
#if (VCOM_CCINST_SUBTP2_3EP_CNT >0)
.p_vcom_ccinst_subtp2_entry = &(t_vcom_func_custp2_arr[0]),
#endif
};
//#define CUST_DEF_TEST_TYPE2//change at/log order--ok
//#define CUST_DEF_TEST_TYPE3//add a vcom---ok
//#define CUST_DEF_TEST_TYPE4//remove a vcom---ok also need to modify dev create/destory
//#define CUST_DEF_TEST_TYPE5//remove rndis--ok also need to modify dev create/destory
//#define CUST_DEF_TEST_TYPE6//change ep--ok
/*
org: if0/1/2/3/4
iep =2/4/6/8/10
oep=1/2/3/4/5
intep=1/2/3/4/5-also in-type
usr cfg:
usb driver still use org epidx, map 2 usr defined ep in below table
should make sure no same ep num in below table
e.g-1. if0 use iep=2 oep=1,intep=1, but user define iep=10, oep=5,intep still 1
epin_remap_custom_tbl[2] =10
epout_remap_custom_tbl[1]=5
epin_remap_custom_tbl[10]=2 //not used but change to another val
epout_remap_custom_tbl[5]=1//not used but change to another val
e.g-2. if0 use iep=2 oep=1,intep=1, if2 use iep=6 oep=3,intep=5. usr want switch if0/2 ep
epin_remap_custom_tbl[2] =6
epout_remap_custom_tbl[1]=3
epin_remap_custom_tbl[6]=2
epout_remap_custom_tbl[3]=1
NOTE:
1 currently, if enbale rndis, rndis should be at the first interface,
if not,rndis enum will have some issue, mostly win host issue, need further debug
2 after add or remove some if, e.g. remmove PPP vcom or add a raw VCOM, user should also modify
ccio dev create logic: not create corresponding dev if removed and create new dev if added.
if still not clear ask EC for help
*/
#ifdef CUST_DEF_TEST_TYPE1
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
#if ((defined LOW_SPEED_SERVICE_ONLY) || (defined LITE_FEATURE_MODE))
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_ORG_CASE)
static multidev_custom_info_st t_multidev_custom_info = {
#ifdef __USER_CODE__
.elem_cnt = 4,
.elem_arr[0] =
{
(const uint8_t*)"vcom3",
multidev_tp_vcom_com,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[1] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
#else
.elem_cnt = 2,
.elem_arr[0] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[1] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
#endif
};
#else
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 2,
.elem_arr[0] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp2_3ep,
},
.elem_arr[1] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp1_2ep,
},
};
#endif
#else
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_ORG_CASE)
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 5,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[4] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
};
#endif
#if (VCOM_CCINST_CASE_SEL==VCOM_CCINST_CUST_CASE)
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 5,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp2_3ep,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp1_2ep,
},
.elem_arr[4] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp2_3ep,
},
};
#endif
#endif
#endif
#ifdef CUST_DEF_TEST_TYPE2
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 5,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[4] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
};
#endif
#ifdef CUST_DEF_TEST_TYPE3
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 6,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[4] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[5] =
{
(const uint8_t*)"vcom3",
multidev_tp_vcom_com,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
};
#endif
#ifdef CUST_DEF_TEST_TYPE4
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 4,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[4] =
{
NULL,
multidev_tp_none,
},
};
#endif
#ifdef CUST_DEF_TEST_TYPE5
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,2,3,4,5,6,7,8,9,10,11,12
};
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 3,
.elem_arr[0] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[1] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
NULL,
multidev_tp_none,
},
};
#endif
#ifdef CUST_DEF_TEST_TYPE6
const uint8_t epin_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 1,6,3,4,5,2,7,8,9,10,11,12
};
const uint8_t epout_remap_custom_tbl[EP_REMAP_CUSTOM_CNT] = {
0, 3,2,1,4,5,6,7,8,9,10,11,12
};
static multidev_custom_info_st t_multidev_custom_info = {
.elem_cnt = 5,
.elem_arr[0] =
{
(const uint8_t*)"rndis",
multidev_tp_rndis,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[1] =
{
(const uint8_t*)"ecm",
multidev_tp_ecm,
ccinst_setting_mainttp_none,
ccinst_setting_subtp_none,
},
.elem_arr[2] =
{
(const uint8_t*)"vcom0",
multidev_tp_vcom_at,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[3] =
{
(const uint8_t*)"vcom1",
multidev_tp_vcom_log,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[4] =
{
(const uint8_t*)"vcom2",
multidev_tp_vcom_ppp,
ccinst_setting_cdc_vcom_maintp,
ccinst_setting_vcom_subtp0_inhrnt,
},
.elem_arr[5] =
{
NULL,
multidev_tp_none,
},
};
#endif
extern uint32_t usbc_dev_int_handler (void);
void USB_IRQ_Handler(void)
{
#if (RTE_USB_EN == 1)
#if MEASURE_USB_INT_TIME
extern void TMU_APTimeReadOpen(UINT32 *sysTime);
uint32_t startTime, endTime;
TMU_APTimeReadOpen(&startTime);
#endif
usbc_dev_int_handler();
#if MEASURE_USB_INT_TIME
TMU_APTimeReadOpen(&endTime);
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, USB_IRQ_Handler_0, P_VALUE, "USB IRQ Time=%d", (endTime-startTime)&0x1FFFFFFF);
#endif
#endif
}
uint8_t usbcustom_epin_id_map(uint8_t ep_idx)
{
if (ep_idx > EP_REMAP_CUSTOM_CNT)
{
return 0xff;
}
return epin_remap_custom_tbl[ep_idx];
}
uint8_t usbcustom_epout_id_map(uint8_t ep_idx)
{
if (ep_idx > EP_REMAP_CUSTOM_CNT)
{
return 0xff;
}
return epout_remap_custom_tbl[ep_idx];
}
uint8_t usbcustom_multidev_ccinfo_maprst(void)
{
uint8_t idx;
usb_func_ccinst_st * p_ccinst;
ccinst_cdc_setting_st *p_ccinst_cdc_set;
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp0_inhrnt_cnt; idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp0_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if (p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst_cdc_set->map_flag = 0;
}
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp1_2ep_cnt;idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp1_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if(p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst_cdc_set->map_flag = 0;
}
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp2_3ep_cnt;idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp2_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if(p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst_cdc_set->map_flag = 0;
}
return 0;
}
uint8_t usbcustom_multidev_ccinfo_map(usbcust_mdcd_ccinfo_st *p_mdcd_ccinfo)
{
uint8_t idx;
usb_func_ccinst_st * p_ccinst;
ccinst_cdc_setting_st *p_ccinst_cdc_set;
uint8_t map_valid = 0;
if(p_mdcd_ccinfo->setting_maintp == ccinst_setting_cdc_vcom_maintp)
{
if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp0_inhrnt)
{
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp0_inhrnt_cnt;idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp0_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if (p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
if (p_ccinst_cdc_set->map_flag ==1)
{
continue;
}
p_ccinst_cdc_set->map_flag = 1;
map_valid = 1;
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
break;
}
}
else if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp1_2ep)
{
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp1_2ep_cnt;idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp1_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if (p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
if (p_ccinst_cdc_set->map_flag ==1)
{
continue;
}
p_ccinst_cdc_set->map_flag = 1;
map_valid = 1;
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
break;
}
}
else if (p_mdcd_ccinfo->setting_subtp== ccinst_setting_vcom_subtp2_3ep)
{
for(idx = 0; idx < t_usbd_multidev_ccinst_res.vcom_ccinst_subtp2_3ep_cnt;idx++)
{
p_ccinst = t_usbd_multidev_ccinst_res.p_vcom_ccinst_subtp2_entry;
if (p_ccinst==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
p_ccinst = p_ccinst+idx;
p_ccinst_cdc_set = p_ccinst->p_cc_setting;
if (p_ccinst_cdc_set==NULL)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
if (p_ccinst_cdc_set->map_flag ==1)
{
continue;
}
p_ccinst_cdc_set->map_flag = 1;
map_valid = 1;
p_mdcd_ccinfo->p_func_ccinst = p_ccinst;
break;
}
}
}
else
{
//other dev not support ccinst
p_mdcd_ccinfo->p_func_ccinst = NULL;
map_valid = 1;
}
//load cnt is limited to MULTI_LOAD_CNT_MAX
#ifndef USB_DRV_SMALL_IMAGE
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_ccinfo_map_1, P_ERROR, 4, \
"clstype %d, inst_id %d, maintp %d, subtp %d", \
p_mdcd_ccinfo->cls_type, \
p_mdcd_ccinfo->inst_id, \
p_mdcd_ccinfo->setting_maintp, \
p_mdcd_ccinfo->setting_subtp);
#endif
if (map_valid==0)
{
#ifndef USB_DRV_SMALL_IMAGE
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_ccinfo_map_2, P_ERROR, 4, \
"clstype %d, inst_id %d, maintp %d, subtp %d", \
p_mdcd_ccinfo->cls_type, \
p_mdcd_ccinfo->inst_id, \
p_mdcd_ccinfo->setting_maintp, \
p_mdcd_ccinfo->setting_subtp);
EC_ASSERT(0, p_mdcd_ccinfo->cls_type, p_mdcd_ccinfo->inst_id, \
(p_mdcd_ccinfo->setting_maintp<<8) |p_mdcd_ccinfo->setting_subtp);
#else
return USBD_MULTIDEV_LOAD_FAIL;
#endif
}
return 0;
}
uint8_t usbcustom_multidev_cfg_reset(void)
{
uint8_t loop_idx;
uint32_t map_flag = 0;
uint32_t cur_flag = 0;
uint8_t ret;
if (epout_remap_custom_tbl[0]!=0)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
for (loop_idx = 1; loop_idx < EP_REMAP_CUSTOM_CNT; loop_idx++)
{
if (epout_remap_custom_tbl[loop_idx] >= EP_REMAP_CUSTOM_CNT)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
cur_flag = (1UL<<epout_remap_custom_tbl[loop_idx]);
if (cur_flag&map_flag)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
map_flag |= (1UL<<epout_remap_custom_tbl[loop_idx]);
}
ret = usbcustom_multidev_ccinfo_maprst();
if(ret)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
#ifdef USBD_EMC_MAC_CONFIG
update_ecm_mac();
#endif
return 0;
}
multidev_custom_info_st* usbcustom_multidev_cfg_update(void)
{
return &t_multidev_custom_info;
}
uint8_t usbcustom_multidev_cfg_end(multidev_load_info_st *p_multidev_load)
{
if ((p_multidev_load->load_cnt+ p_multidev_load->filter_cnt ) != t_multidev_custom_info.elem_cnt)
{
return USBD_MULTIDEV_LOAD_FAIL;
}
if (p_multidev_load->load_cnt > MULTI_DEV_LOADCNT_MAX)
{
//load cnt is limited to MULTI_LOAD_CNT_MAX
#ifndef USB_DRV_SMALL_IMAGE
ECOMM_TRACE(UNILOG_PLA_DRIVER, usbcustom_multidev_cfg_end_1, P_ERROR, 1,"p_multidev_load->load_cnt %x", p_multidev_load->load_cnt);
#endif
return USBD_MULTIDEV_LOAD_FAIL;
}
return 0;
}
uint8_t *usbcustom_multidev_strdesc(usbcust_mdcd_strdesc_st *p_mdcd_strdesc)
{
uint8_t* p_intf_str_desc = (uint8_t*)"default";
switch(p_mdcd_strdesc->cls_type)
{
case multidev_tp_rndis:
p_intf_str_desc = (uint8_t*)"rndis";
break;
case multidev_tp_ecm:
p_intf_str_desc = (uint8_t*)"ecm";
break;
case multidev_tp_vcom_at:
p_intf_str_desc = (uint8_t*)"at";
break;
case multidev_tp_vcom_log:
p_intf_str_desc = (uint8_t*)"log";
break;
case multidev_tp_vcom_ppp:
p_intf_str_desc = (uint8_t*)"ppp";
break;
case multidev_tp_vcom_com:
p_intf_str_desc = (uint8_t*)"com";
break;
default:
break;
}
#ifndef USB_DRV_SMALL_IMAGE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidevstr_desc_1, P_DEBUG, \
"cls_type %d, inst_id 0x%x, name %s, intf string %s", \
p_mdcd_strdesc->cls_type, \
p_mdcd_strdesc->inst_id, \
p_mdcd_strdesc->p_func_name, \
p_intf_str_desc);
#endif
return p_intf_str_desc;
}
uint8_t usbcustom_multidev_cmndesc(usbcust_mdcd_cmndesc_st *p_mdcd_cmndesc)
{
usbcust_cmndesc_data_st *p_cmndesc_data= &(p_mdcd_cmndesc->t_cmndesc_data);
switch(p_mdcd_cmndesc->cls_type)
{
case multidev_tp_rndis:
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0xE0;
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x01;
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x03;
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
#ifndef USB_DRV_SMALL_IMAGE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
p_mdcd_cmndesc->p_func_name, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
#endif
break;
case multidev_tp_ecm:
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0x02;
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x06;
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x00;
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
#ifndef USB_DRV_SMALL_IMAGE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
p_mdcd_cmndesc->p_func_name, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
#endif
break;
case multidev_tp_vcom_at:
case multidev_tp_vcom_log:
case multidev_tp_vcom_ppp:
case multidev_tp_vcom_com:
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass = 0x02;
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass = 0x02;
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol = 0x01;
p_cmndesc_data->b_intf_ctrl_desc_upd = 1;
#ifndef USB_DRV_SMALL_IMAGE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_cmndesc_1, P_DEBUG, \
"name %s, cls = 0x%x, subcls 0x%x, protocol 0x%x", \
p_mdcd_cmndesc->p_func_name, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceSubClass, \
p_cmndesc_data->intf_ctrl_desc.bInterfaceProtocol);
#endif
break;
default:
break;
}
return 0;
}
uint8_t usbcustom_multidev_ctrl_proc(usbcust_md_ctrl_st* p_usbcust_md_ctrl)
{
// t_ctl_req.cmd Bit 31 : 0 host to dev, 1 dev to host
#ifndef USB_DRV_SMALL_IMAGE
ECPLAT_PRINTF(UNILOG_PLA_DRIVER, usbcustom_multidev_ctrl_proc_1, P_DEBUG, \
"cls_type = %d, inst_id %d, name %s, req 0x%x", \
p_usbcust_md_ctrl->cls_type, \
p_usbcust_md_ctrl->inst_id, \
p_usbcust_md_ctrl->p_func_name, \
p_usbcust_md_ctrl->t_ctl_req.cmd);
#if 0
ECPLAT_DUMP(UNILOG_PLA_DRIVER, usbcustom_multidev_ctrl_proc_2, P_DEBUG, \
"clsdev req data:", \
p_usbcust_md_ctrl->t_ctl_req.len, \
p_usbcust_md_ctrl->t_ctl_req.buf);
#endif
#endif
#ifdef __USER_CODE__
extern void usb_ctrl_pre_proc(usbcust_md_ctrl_st *);
usb_ctrl_pre_proc(p_usbcust_md_ctrl);
#endif
p_usbcust_md_ctrl->t_ctl_req.cmd &= (~(0x1UL<<31));
return 0;
}
/**
\fn usblpw_innophy_enh_drv_strenth(void)
\brief used by USB driver, called when USBC init.
user could modify the para below for differnt use cases
\note cfg usb phy para for none standard usb cable,e.g. fly wire in production line
0x4d0b0030: Enables pre-emphasis----should keep default val set below
0x4d0b0040: b[5:3] Tx HS pre_emphasize strength configure, 3b111 represents the
strongest , 3b000 the weakest
0x4d0b0064: b[6:3] Rx squelch trigger point configures
0x4d0b0124: b[4:2] HS eye height tuning
if any problem ,contact EC
*/
void usblpw_innophy_enh_drv_strenth(void)
{
volatile uint32_t* addr = (volatile uint32_t*)0x4d0b0030;
* addr = (* addr &~ (0x7<<0)) | (0x5<<0);
addr = (volatile uint32_t*)0x4d0b0040;
* addr = (* addr &~ (0x7<<3)) | (0x4<<3);
addr = (volatile uint32_t*)0x4d0b0064;
* addr = (* addr &~ (0xf<<3)) | (0x6<<3);
addr = (volatile uint32_t*)0x4d0b0124;
* addr = (* addr &~ (0x7<<2)) | (0x5<<2);
}

View File

@@ -0,0 +1,174 @@
#include <stdio.h>
#include "usbd_multi_clstype.h"
#define USB_DEV_QUALIFIER_DESC_ARR_SIZE 0x0A
#define DEF_LANGID_STR 0x409
#define DEF_MANUFACT_STR "AirM2M";
#define DEF_PRODUCT_HS_STR "AirM2M Compo";
#define DEF_SER_NUM_HS_STR "000000000001"
#define DEF_CFG_HS_STR "Compo Config"
#define DEF_INTF_HS_STR "Compo Interface"
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
#define USB_STRING_DESCRIPTOR_TYPE 0x03
#define USB_SIZ_STRING_LANGID 4
#define USB_SIZ_DEVICE_DESC 0x12
#define LOBYTE(x) ((uint8_t)(x & 0x00FF))
#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8))
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
uint32_t udev_last_err = 0;
uint8_t usbd_dev_desc_arr[USB_SIZ_DEVICE_DESC] =
{
0x12, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00,
0x02, /* bcdUSB = 2.00 */
0xEF, /* bDeviceClass: IAD */
0x02, /* bDeviceSubClass */
0x01, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0xd1,
0x19, /* idVendor = 0x19d1 */
0x01,
0x00, /* idProduct = 0x0001 */
0x00,
0x02, /* bcdDevice = 2.00 */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */
0x01 /* bNumConfigurations */
};
/* USB Standard Device Descriptor */
uint8_t usbd_dev_qualifier_desc_arr[USB_DEV_QUALIFIER_DESC_ARR_SIZE] =
{
USB_DEV_QUALIFIER_DESC_ARR_SIZE,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0xEF,
0x02,
0x01,
0x40,
0x01,
0x00,
};
/* USB Standard Device Descriptor */
uint8_t usbd_dev_langid_desc[USB_SIZ_STRING_LANGID] =
{
USB_SIZ_STRING_LANGID,
USB_DESC_TYPE_STRING,
LOBYTE(DEF_LANGID_STR),
HIBYTE(DEF_LANGID_STR),
};
uint8_t *usbcustom_product_str_desc(void)
{
return (uint8_t *)DEF_PRODUCT_HS_STR;
}
uint8_t *usbcustom_manufacture_str_desc(void)
{
return (uint8_t *)DEF_MANUFACT_STR;
}
uint8_t *usbcustom_ser_str_desc(void)
{
return (uint8_t *)DEF_SER_NUM_HS_STR;
}
uint8_t *usbcustom_cfg_str_desc(void)
{
return (uint8_t *)DEF_CFG_HS_STR;
}
uint8_t *usbcustom_intf_str_desc(void)
{
return (uint8_t *)DEF_INTF_HS_STR;
}
uint8_t *usbcustom_qulifier_desc(void)
{
return usbd_dev_qualifier_desc_arr;
}
uint8_t usbcustom_cfg_remote_wkup_bit(void)
{
return 1;
}
uint8_t usbcustom_cfg_self_powered_bit(void)
{
return 0;
}
uint8_t usbcustom_cfg_max_power(void)
{
return 100;
}
void udev_notify_init(void)
{
}
void udev_notify_device_reset (uint8_t speed)
{
}
void udev_notify_device_config (void)
{
}
void udev_notify_device_suspend(void)
{
}
void udev_notify_device_resume(void)
{
}
void udev_notify_device_connect (void)
{
}
void udev_notify_device_disconnect (void)
{
}
void udev_set_last_err(uint32_t err_no)
{
udev_last_err = err_no;
}
uint32_t udev_get_last_err(void)
{
return udev_last_err;
}

View File

@@ -0,0 +1,196 @@
#include "string.h"
#include "cmsis_os2.h"
#include "hal_misc.h"
#include <stdlib.h>
#include <stdio.h>
#include "usb_bl_api.h"
int vcomx_isconnect(uint8_t vcom_num);
int vcomx_get_in_waiting(uint8_t vcom_num);
int vcomx_poll_rx(uint8_t vcom_num, uint32_t timeout);
int vcomx_recv(uint8_t vcom_num, uint8_t* buf, uint16_t len);
int vcomx_get_out_avail(uint8_t vcom_num);
int vcomx_poll_tx(uint8_t vcom_num, uint32_t timeout);
int vcomx_send(uint8_t vcom_num, uint8_t* buf, uint16_t len);
#ifdef VCOM_DBGEN
void vcom_dbg_putchar(uint8_t ch);
void vcomdbg_hex(uint32_t hex)
{
uint16_t val;
for (int32_t idx = 28; idx >=0; idx-=4)
{
val = ((hex>>idx)&0xf) + 0x30;
if(val>=0x3a)
{
val = val + 0x27;
}
vcom_dbg_putchar(val);
}
}
void vcomdbg_str(uint8_t* str)
{
while(*str)
{
vcom_dbg_putchar(*str);
str++;
}
}
void vcomdbg_str_and_hex(uint8_t* str, uint32_t hex)
{
vcomdbg_str(str);
//vcomdbg_str((uint8_t*)"\r\n");
vcomdbg_hex(hex);
vcomdbg_str((uint8_t*)"\r\n");
}
#endif
void vcom_app_delay(uint32_t ticks)
{
volatile int us_cnt = 0;
volatile int loop_in_us;
//depend on code speed, add 6 for flash code at 50M, cpu 204m
for (us_cnt = 0; us_cnt < ticks*1000; us_cnt+=6){
loop_in_us = 0;
while(loop_in_us++< 70);
}
}
int vcom_app_recv_proc(uint8_t vcom_num, uint8_t* rcvbuf_ptr, uint32_t size, uint8_t timeout)
{
int rxwait_cnt;
int poll_stat;
uint8_t recvd_size = 0;
int byte_cnt = 0;
uint32_t ticks_tmout = timeout; // 1tick for 1ms
uint32_t ticks_elapsed = 0;
uint32_t ticks_step = 1;
if (size ==0)
{
return 0;
}
while(1)
{
if (vcomx_isconnect(vcom_num) <=0)
{
VCDBG_STR_AND_HEX("vcom[%d] not connected%x \r\n", vcom_num);
return ERR_DEV_NO_CONNECT;
}
//rxwait_cnt = p_serial_vcom->p_ops->get_in_waiting(p_serial_vcom);
rxwait_cnt = vcomx_get_in_waiting(vcom_num);
if (rxwait_cnt <0)
{
VCDBG_STR_AND_HEX("get_in_waiting err %d \r\n", rxwait_cnt);
return rxwait_cnt;
}
if (rxwait_cnt ==0)
{
if (ticks_elapsed >=ticks_tmout)
{
VCDBG_STR_AND_HEX("recv timeout, recved bytes %d \r\n", recvd_size);
return recvd_size;
}
//poll_stat = p_serial_vcom->p_ops->poll_rx(p_serial_vcom, 0);
poll_stat =vcomx_poll_rx(vcom_num, 0);
if ((poll_stat <0) && (poll_stat!=ERR_DEV_RX_TIMOUT))
{
VCDBG_STR_AND_HEX("recv poll state break %d \r\n", poll_stat);
return poll_stat;
}
vcom_app_delay(ticks_step);
ticks_elapsed += ticks_step;
continue;
}
if (rxwait_cnt> size)
{
rxwait_cnt = size;
}
//byte_cnt = p_serial_vcom->p_ops->recv(p_serial_vcom, rcvbuf_ptr, rxwait_cnt);
byte_cnt = vcomx_recv(vcom_num, rcvbuf_ptr, rxwait_cnt);
if (byte_cnt < 0)
{
VCDBG_STR_AND_HEX("recv state break %d \r\n", byte_cnt);
return byte_cnt;
}
recvd_size += byte_cnt;
if (recvd_size>=size)
{
return recvd_size;
}
}
return 0;
}
int vcom_app_send_proc(uint8_t vcom_num, uint8_t* sndbuf_ptr, uint32_t size, uint8_t timeout)
{
int txavail_cnt;
int poll_stat;
int byte_cnt;
uint8_t sended_size = 0;
uint32_t ticks_tmout = timeout; // 1tick for 1ms
uint32_t ticks_elapsed = 0;
uint32_t ticks_step = 1;
while(1)
{
if (vcomx_isconnect(vcom_num) <= 0)
{
VCDBG_STR_AND_HEX("vcom[%d] not connected \r\n", vcom_num);
return ERR_DEV_NO_CONNECT;
}
//txavail_cnt = p_serial_vcom->p_ops->get_out_avail(p_serial_vcom);
txavail_cnt = vcomx_get_out_avail(vcom_num);
if (txavail_cnt == 0)
{
if (ticks_elapsed >=ticks_tmout)
{
VCDBG_STR_AND_HEX("vcom[%d] \r\n", vcom_num);
VCDBG_STR_AND_HEX("send timeout, sended bytes %x \r\n", sended_size);
return sended_size;
}
//poll_stat = p_serial_vcom->p_ops->poll_tx(p_serial_vcom, 0);
poll_stat = vcomx_poll_tx(vcom_num, 0);
if ((poll_stat <0) && (poll_stat!=ERR_DEV_RX_TIMOUT))
{
VCDBG_STR_AND_HEX("send poll state break %d \r\n", poll_stat);
return poll_stat;
}
vcom_app_delay(ticks_step);
ticks_elapsed += ticks_step;
continue;
}
if (size < txavail_cnt)
{
txavail_cnt = size;
}
//byte_cnt = p_serial_vcom->p_ops->send(p_serial_vcom, sndbuf_ptr, txavail_cnt);
byte_cnt = vcomx_send(vcom_num, sndbuf_ptr, txavail_cnt);
if (byte_cnt <0)
{
VCDBG_STR_AND_HEX("send state break %d \r\n", byte_cnt);
return byte_cnt;
}
sended_size +=byte_cnt;
if (sended_size>=size)
{
return sended_size;
}
}
}

View File

@@ -0,0 +1,378 @@
#include "ec618.h"
#include "string.h"
#include "cmsis_os2.h"
#include "hal_misc.h"
#include <stdlib.h>
#include <stdio.h>
#include "bl_bsp.h"
#include "usb_bl_api.h"
int vcomx_isconnect(uint8_t vcom_num);
int vcomx_get_in_waiting(uint8_t vcom_num);
int vcomx_poll_rx(uint8_t vcom_num, uint32_t timeout);
int vcomx_recv(uint8_t vcom_num, uint8_t* buf, uint16_t len);
int vcomx_get_out_avail(uint8_t vcom_num);
int vcomx_poll_tx(uint8_t vcom_num, uint32_t timeout);
int vcomx_send(uint8_t vcom_num, uint8_t* buf, uint16_t len);
typedef enum
{
vcom_step_idle = 0,
vcom_step_recv ,
vcom_step_send ,
vcom_step_busy_sending ,
}vcom_app_step_type;
#define VCOM_STATE_IDLE 0
#define VCOM_TEST_BUF_SIZE 0x400
typedef struct
{
//uint8_t recv_en;
//uint8_t send_en;
vcom_app_step_type step;
uint32_t received_len;
uint32_t sended_len;
uint8_t vcom_rcvbuff[VCOM_TEST_BUF_SIZE];
uint8_t vcom_sndbuff[VCOM_TEST_BUF_SIZE];
}vcom_app_ctx_st;
#define VCOM_NUM_MAX 3
vcom_app_ctx_st vcom_app_ctx[VCOM_NUM_MAX];
void vcom_app_ctx_init(void)
{
memset(&vcom_app_ctx, 0, sizeof(vcom_app_ctx));
}
int vcom_app_ctx_is_idlestep(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
if(vcom_app_ctx[vcom_num].step == vcom_step_idle)
{
return 1;
}
return 0;
}
uint8_t vcom_app_ctx_is_recvstep(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return 0;
}
if(vcom_app_ctx[vcom_num].step == vcom_step_recv)
{
return 1;
}
return 0;
}
uint8_t vcom_app_ctx_is_sendstep(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return 0;
}
if(vcom_app_ctx[vcom_num].step == vcom_step_send)
{
return 1;
}
return 0;
}
uint8_t vcom_app_ctx_is_busysending(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return 0;
}
if(vcom_app_ctx[vcom_num].step == vcom_step_busy_sending)
{
return 1;
}
return 0;
}
void vcom_app_ctx_set_step(uint8_t vcom_num, vcom_app_step_type step)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return;
}
vcom_app_ctx[vcom_num].step = step;
return ;
}
int vcom_app_get_rcvbuff_size(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
return sizeof(vcom_app_ctx[vcom_num].vcom_rcvbuff);
}
uint8_t* vcom_app_get_rcvbuff_ptr(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return NULL;
}
return &(vcom_app_ctx[vcom_num].vcom_rcvbuff[0]);
}
int vcom_app_get_sndbuff_size(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
return sizeof(vcom_app_ctx[vcom_num].vcom_sndbuff);
}
uint8_t* vcom_app_get_sndbuff_ptr(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return NULL;
}
return &(vcom_app_ctx[vcom_num].vcom_sndbuff[0]);
}
int vcom_app_update_recved_size(uint8_t vcom_num, uint32_t size)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
vcom_app_ctx[vcom_num].received_len = size;
return 0;
}
int vcom_app_update_sended_size(uint8_t vcom_num, uint32_t size)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
vcom_app_ctx[vcom_num].sended_len = size;
return 0;
}
int vcom_app_get_recved_size(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
return vcom_app_ctx[vcom_num].received_len;
}
int vcom_app_get_sended_size(uint8_t vcom_num)
{
if (vcom_num>=VCOM_NUM_MAX)
{
VCDBG_STR_AND_HEX("vcom_num(%d) error \r\n", vcom_num);
return -1;
}
return vcom_app_ctx[vcom_num].sended_len;
}
int vcom_app_send_proc(uint8_t vcom_num, uint8_t* sndbuf_ptr, uint32_t size, uint8_t timeout);
int vcom_app_recv_proc(uint8_t vcom_num, uint8_t* rcvbuf_ptr, uint32_t size, uint8_t timeout);
void vcom_app_delay(uint32_t ticks);
void vcom_loopback_test(void *p)
{
int ret;
int txavail_cnt;
//#if DEVICE_VCOM_INSTANCE
uint32_t sended_size;
uint8_t * send_buf_ptr;
uint8_t * recv_buf_ptr;
vcom_app_ctx_init();
int vcom_num = 0;
VCDBG_STR("uart_loopback_test start \r\n");
while(1)
{
vcom_app_delay(10);
vcom_num = vcom_num+1;
vcom_num = vcom_num%VCOM_NUM_MAX;
while(1)
{
if (vcomx_isconnect(vcom_num) ==0)
{
vcom_app_delay(1000);
break;
}
if (vcom_app_ctx_is_idlestep(vcom_num)==1)
{
if (vcomx_isconnect(vcom_num) ==0)
{
vcom_app_delay(20);
break;
}
vcom_app_ctx_set_step(vcom_num, vcom_step_recv);
VCDBG_STR_AND_HEX("vcom(%d) [recv] \r\n", vcom_num);
}
if (vcom_app_ctx_is_recvstep(vcom_num)==1)
{
ret= vcom_app_recv_proc(vcom_num,
vcom_app_get_rcvbuff_ptr(vcom_num),
vcom_app_get_rcvbuff_size(vcom_num), 1);
if (ret <=0)
{
vcom_app_delay(1);
break;
}
vcom_app_update_recved_size(vcom_num, ret);
vcom_app_update_sended_size(vcom_num, 0);
vcom_app_ctx_set_step(vcom_num, vcom_step_send);
VCDBG_STR_AND_HEX("vcom(%d) [recv] ->[send] \r\n", vcom_num);
VCDBG_STR_AND_HEX("ret %d \r\n",ret);
break;
}
if (vcom_app_ctx_is_sendstep(vcom_num)==1)
{
if (vcom_app_get_recved_size(vcom_num) <0)
{
VCDBG_STR_AND_HEX("vcom(%d) [send] recved_size <0, ->[idle] \r\n", vcom_num);
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
vcom_app_update_recved_size(vcom_num, 0);
break;
}
sended_size = vcom_app_get_sended_size(vcom_num);
recv_buf_ptr= vcom_app_get_rcvbuff_ptr(vcom_num);
send_buf_ptr = vcom_app_get_rcvbuff_ptr(vcom_num);
if (sended_size >=vcom_app_get_recved_size(vcom_num))
{
VCDBG_STR_AND_HEX("vcom(%d) [send] unneeded->[idle]", vcom_num);
VCDBG_STR_AND_HEX("recved %d\r\n",
vcom_app_get_recved_size(vcom_num));
VCDBG_STR_AND_HEX("sended %d\r\n",
vcom_app_get_sended_size(vcom_num));
break;
}
txavail_cnt = vcom_app_get_sndbuff_size(vcom_num);
if ((txavail_cnt+sended_size) > vcom_app_get_recved_size(vcom_num))
{
txavail_cnt = vcom_app_get_recved_size(vcom_num) - sended_size;
}
memcpy(send_buf_ptr+sended_size, recv_buf_ptr+sended_size, txavail_cnt);
ret = vcom_app_send_proc(vcom_num, send_buf_ptr+sended_size, txavail_cnt, 1);
if (ret <0)
{
VCDBG_STR_AND_HEX("vcom(%d) [send] , ->[idle] \r\n", vcom_num);
VCDBG_STR_AND_HEX("fail %08x %d\r\n",ret);
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
vcom_app_update_recved_size(vcom_num, 0);
break;
}
sended_size+=ret;
vcom_app_update_sended_size(vcom_num, ret);
if (sended_size >=vcom_app_get_recved_size(vcom_num))
{
VCDBG_STR_AND_HEX("vcom(%d) [send] ->[idle] finish \r\n", vcom_num);
VCDBG_STR_AND_HEX("recved %d \r\n", vcom_app_get_recved_size(vcom_num));
VCDBG_STR_AND_HEX("sended %d \r\n", vcom_app_get_sended_size(vcom_num));
vcom_app_ctx_set_step(vcom_num, vcom_step_idle);
vcom_app_update_recved_size(vcom_num, 0);
break;
}
vcom_app_ctx_set_step(vcom_num, vcom_step_busy_sending);
break;
}
if (vcom_app_ctx_is_busysending(vcom_num)==1)
{
vcom_app_delay(1);
vcom_app_ctx_set_step(vcom_num, vcom_step_send);
break;
}
}
}
VCDBG_STR("uart_loopback_test end \r\n");
}
void vcom_urcprint_test(void)
{
uint8_t vcom_num = 0;
int cnt = 0;
while(cnt++<2000)
{
vcom_app_delay(10);
vcom_num = vcom_num+1;
vcom_num = vcom_num%VCOM_NUM_MAX;
SelNormalOrURCPrint(1);
BSP_URCSetCfg(1, 115200, URCVCom0PrintType+vcom_num, vcom_num);
printf("URC PRINT %d\r\n", vcom_num);
SelNormalOrURCPrint(0);
printf("NO URC PRINT\r\n");
}
}
uint32_t BSP_UsbInit(void);
void WDT_stop(void);
void vcom_app_delay(uint32_t ticks);
void vcom_urc_test_entry(void)
{
WDT_stop();// stop watchdog for test
extern uint8_t usbstack_clear_ctx_stat(void);
extern void usbstack_set_ctx_vbus_mode(uint8_t vbus_mode_en, uint8_t vbus_pad_idx);
usbstack_clear_ctx_stat();
usbstack_set_ctx_vbus_mode(0,0xf);
BSP_UsbInit();
extern void vcom_urcprint_test(void);
vcom_urcprint_test();
void vcom_loopback_test(void *p);
vcom_loopback_test(NULL);
while(1);
}

View File

@@ -0,0 +1,209 @@
/****************************************************************************
*
* Copy right: 2017-, Copyrigths of AirM2M Ltd.
* File name: wdt.c
* Description: EC618 wdt driver source file
* History: Rev1.0 2018-07-18
*
****************************************************************************/
#include "wdt.h"
#include "clock.h"
#include "slpman.h"
#ifdef PM_FEATURE_ENABLE
/** \brief Internal used data structure */
typedef struct _wdt_database
{
bool isInited; /**< whether wdt has been initialized */
bool wdtStartStatus; /**< wdt enable status, used for low power restore */
WdtConfig_t wdtConfig; /**< wdt configuration, used for low power restore */
} WdtDatabase_t;
static WdtDatabase_t gWdtDataBase = {0};
/**
\fn static void WDT_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
\brief Perform necessary preparations before sleep
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void WDT_enterLowPowerStatePrepare(void* pdata, slpManLpState state)
{
switch (state)
{
case SLPMAN_SLEEP1_STATE:
if(gWdtDataBase.isInited == true)
{
gWdtDataBase.wdtStartStatus = WDT_getStartStatus();
//disable clock
CLOCK_clockDisable(PCLK_WDG);
CLOCK_clockDisable(FCLK_WDG);
}
break;
default:
break;
}
}
/**
\fn static void WDT_exitLowPowerStateRestore(void* pdata, slpManLpState state)
\brief Restore after exit from sleep
\param[in] pdata pointer to user data, not used now
\param[in] state low power state
*/
static void WDT_exitLowPowerStateRestore(void* pdata, slpManLpState state)
{
switch (state)
{
case SLPMAN_SLEEP1_STATE:
if(gWdtDataBase.isInited == true)
{
//enable clock
CLOCK_clockEnable(PCLK_WDG);
CLOCK_clockEnable(FCLK_WDG);
WDT_unlock();
WDT->CTRL = (WDT->CTRL &~ WDT_CTRL_MODE_Msk) | EIGEN_VAL2FLD(WDT_CTRL_MODE, gWdtDataBase.wdtConfig.mode);
WDT_unlock();
WDT->TOVR = gWdtDataBase.wdtConfig.timeoutValue;
if(gWdtDataBase.wdtStartStatus)
WDT_start();
}
break;
default:
break;
}
}
#endif
void WDT_unlock(void)
{
WDT->LOCK = 0xABABU;
}
void WDT_kick(void)
{
uint32_t mask = SaveAndSetIRQMask();
WDT_unlock();
WDT->CCR = WDT_CCR_CNT_CLR_Msk;
RestoreIRQMask(mask);
}
void WDT_getDefaultConfig(WdtConfig_t *config)
{
ASSERT(config);
config->mode = WDT_INTERRUPT_ONLY_MODE;
config->timeoutValue = 0xFFFFU;
}
void WDT_init(const WdtConfig_t *config)
{
ASSERT(config);
#ifdef PM_FEATURE_ENABLE
if(gWdtDataBase.isInited == true)
{
return;
}
slpManRegisterPredefinedBackupCb(SLP_CALLBACK_WDT_MODULE, WDT_enterLowPowerStatePrepare, NULL);
slpManRegisterPredefinedRestoreCb(SLP_CALLBACK_WDT_MODULE, WDT_exitLowPowerStateRestore, NULL);
gWdtDataBase.isInited = true;
gWdtDataBase.wdtConfig = *config;
#endif
//enable clock
CLOCK_clockEnable(PCLK_WDG);
CLOCK_clockEnable(FCLK_WDG);
WDT_unlock();
WDT->CTRL = (WDT->CTRL &~ WDT_CTRL_MODE_Msk) | EIGEN_VAL2FLD(WDT_CTRL_MODE, config->mode);
WDT_unlock();
WDT->TOVR = config->timeoutValue;
}
void WDT_deInit(void)
{
#ifdef PM_FEATURE_ENABLE
if(gWdtDataBase.isInited == false)
{
return;
}
slpManUnregisterPredefinedBackupCb(SLP_CALLBACK_WDT_MODULE);
slpManUnregisterPredefinedRestoreCb(SLP_CALLBACK_WDT_MODULE);
gWdtDataBase.isInited = false;
#endif
//disable clock
CLOCK_clockDisable(PCLK_WDG);
CLOCK_clockDisable(FCLK_WDG);
}
void WDT_start(void)
{
uint32_t mask = SaveAndSetIRQMask();
WDT_unlock();
WDT->CTRL |= WDT_CTRL_ENABLE_Msk;
RestoreIRQMask(mask);
}
void WDT_stop(void)
{
uint32_t mask = SaveAndSetIRQMask();
WDT_unlock();
WDT->CTRL &= ~WDT_CTRL_ENABLE_Msk;
RestoreIRQMask(mask);
}
uint32_t WDT_getInterruptFlags(void)
{
return WDT->STAT & WDT_STAT_ISTAT_Msk;
}
void WDTclearInterruptFlags(uint32_t mask)
{
uint32_t msk = SaveAndSetIRQMask();
WDT_unlock();
WDT->ICR = WDT_ICR_ICLR_Msk;
RestoreIRQMask(msk);
}
WdtMode_e WDT_getMode(void)
{
return (WdtMode_e)EIGEN_FLD2VAL(WDT_CTRL_MODE, WDT->CTRL);
}
bool WDT_getStartStatus(void)
{
return (bool)EIGEN_FLD2VAL(WDT_CTRL_ENABLE, WDT->CTRL);
}

View File

@@ -0,0 +1,15 @@
#include <stdbool.h>
bool LPUSART_IsRxActive(void)
{
return 0;
}
void LPUSART_ClearStopFlag(void)
{
}
void LPUSART_SetStopFlag(void)
{
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This memcpy routine is optimised for Cortex-M3/M4 cores with/without
unaligned access.
If compiled with GCC, this file should be enclosed within following
pre-processing check:
if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
Prototype: void *memcpy (void *dst, const void *src, size_t count);
The job will be done in 5 steps.
Step 1: Align src/dest pointers, copy mis-aligned if fail to align both
Step 2: Repeatedly copy big block size of __OPT_BIG_BLOCK_SIZE
Step 3: Repeatedly copy big block size of __OPT_MID_BLOCK_SIZE
Step 4: Copy word by word
Step 5: Copy byte-to-byte
Tunable options:
__OPT_BIG_BLOCK_SIZE: Size of big block in words. Default to 64.
__OPT_MID_BLOCK_SIZE: Size of big block in words. Default to 16.
*/
#ifndef __OPT_BIG_BLOCK_SIZE
#define __OPT_BIG_BLOCK_SIZE (4 * 16)
#endif
#ifndef __OPT_MID_BLOCK_SIZE
#define __OPT_MID_BLOCK_SIZE (4 * 4)
#endif
#if __OPT_BIG_BLOCK_SIZE == 16
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12
#elif __OPT_BIG_BLOCK_SIZE == 32
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12,16,20,24,28
#elif __OPT_BIG_BLOCK_SIZE == 64
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60
#else
#error "Illegal __OPT_BIG_BLOCK_SIZE"
#endif
#if __OPT_MID_BLOCK_SIZE == 8
#define BEGIN_UNROLL_MID_BLOCK \
.irp offset, 0,4
#elif __OPT_MID_BLOCK_SIZE == 16
#define BEGIN_UNROLL_MID_BLOCK \
.irp offset, 0,4,8,12
#else
#error "Illegal __OPT_MID_BLOCK_SIZE"
#endif
#define END_UNROLL .endr
.syntax unified
.text
.align 2
.global memcpy
.thumb
.thumb_func
.type memcpy, %function
memcpy:
@ r0: dst
@ r1: src
@ r2: len
#ifdef __ARM_FEATURE_UNALIGNED
/* In case of UNALIGNED access supported, ip is not used in
function body. */
mov ip, r0
#else
push {r0}
#endif
orr r3, r1, r0
ands r3, r3, #3
bne .Lmisaligned_copy
.Lbig_block:
subs r2, __OPT_BIG_BLOCK_SIZE
blo .Lmid_block
/* Kernel loop for big block copy */
.align 2
.Lbig_block_loop:
BEGIN_UNROLL_BIG_BLOCK
#ifdef __ARM_ARCH_7EM__
ldr r3, [r1], #4
str r3, [r0], #4
END_UNROLL
#else /* __ARM_ARCH_7M__ */
ldr r3, [r1, \offset]
str r3, [r0, \offset]
END_UNROLL
adds r0, __OPT_BIG_BLOCK_SIZE
adds r1, __OPT_BIG_BLOCK_SIZE
#endif
subs r2, __OPT_BIG_BLOCK_SIZE
bhs .Lbig_block_loop
.Lmid_block:
adds r2, __OPT_BIG_BLOCK_SIZE - __OPT_MID_BLOCK_SIZE
blo .Lcopy_word_by_word
/* Kernel loop for mid-block copy */
.align 2
.Lmid_block_loop:
BEGIN_UNROLL_MID_BLOCK
#ifdef __ARM_ARCH_7EM__
ldr r3, [r1], #4
str r3, [r0], #4
END_UNROLL
#else /* __ARM_ARCH_7M__ */
ldr r3, [r1, \offset]
str r3, [r0, \offset]
END_UNROLL
adds r0, __OPT_MID_BLOCK_SIZE
adds r1, __OPT_MID_BLOCK_SIZE
#endif
subs r2, __OPT_MID_BLOCK_SIZE
bhs .Lmid_block_loop
.Lcopy_word_by_word:
adds r2, __OPT_MID_BLOCK_SIZE - 4
blo .Lcopy_less_than_4
/* Kernel loop for small block copy */
.align 2
.Lcopy_word_by_word_loop:
ldr r3, [r1], #4
str r3, [r0], #4
subs r2, #4
bhs .Lcopy_word_by_word_loop
.Lcopy_less_than_4:
adds r2, #4
beq .Ldone
lsls r2, r2, #31
itt ne
ldrbne r3, [r1], #1
strbne r3, [r0], #1
bcc .Ldone
#ifdef __ARM_FEATURE_UNALIGNED
ldrh r3, [r1]
strh r3, [r0]
#else
ldrb r3, [r1]
strb r3, [r0]
ldrb r3, [r1, #1]
strb r3, [r0, #1]
#endif /* __ARM_FEATURE_UNALIGNED */
.Ldone:
#ifdef __ARM_FEATURE_UNALIGNED
mov r0, ip
#else
pop {r0}
#endif
bx lr
.align 2
.Lmisaligned_copy:
#ifdef __ARM_FEATURE_UNALIGNED
/* Define label DST_ALIGNED to BIG_BLOCK. It will go to aligned copy
once destination is adjusted to aligned. */
#define Ldst_aligned Lbig_block
/* Copy word by word using LDR when alignment can be done in hardware,
i.e., SCTLR.A is set, supporting unaligned access in LDR and STR. */
cmp r2, #8
blo .Lbyte_copy
/* if src is aligned, just go to the big block loop. */
lsls r3, r1, #30
beq .Ldst_aligned
#else
/* if len < 12, misalignment adjustment has more overhead than
just byte-to-byte copy. Also, len must >=8 to guarantee code
afterward work correctly. */
cmp r2, #12
blo .Lbyte_copy
#endif /* __ARM_FEATURE_UNALIGNED */
/* Align dst only, not trying to align src. That is the because
handling of aligned src and misaligned dst need more overhead than
otherwise. By doing this the worst case is when initial src is aligned,
additional up to 4 byte additional copy will executed, which is
acceptable. */
ands r3, r0, #3
beq .Ldst_aligned
rsb r3, #4
subs r2, r3
lsls r3, r3, #31
itt ne
ldrbne r3, [r1], #1
strbne r3, [r0], #1
bcc .Ldst_aligned
#ifdef __ARM_FEATURE_UNALIGNED
ldrh r3, [r1], #2
strh r3, [r0], #2
b .Ldst_aligned
#else
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrb r3, [r1], #1
strb r3, [r0], #1
/* Now that dst is aligned */
.Ldst_aligned:
/* if r1 is aligned now, it means r0/r1 has the same misalignment,
and they are both aligned now. Go aligned copy. */
ands r3, r1, #3
beq .Lbig_block
/* dst is aligned, but src isn't. Misaligned copy. */
push {r4, r5}
subs r2, #4
/* Backward r1 by misaligned bytes, to make r1 aligned.
Since we need to restore r1 to unaligned address after the loop,
we need keep the offset bytes to ip and sub it from r1 afterward. */
subs r1, r3
rsb ip, r3, #4
/* Pre-load on word */
ldr r4, [r1], #4
cmp r3, #2
beq .Lmisaligned_copy_2_2
cmp r3, #3
beq .Lmisaligned_copy_3_1
.macro mis_src_copy shift
1:
#ifdef __ARM_BIG_ENDIAN
lsls r4, r4, \shift
#else
lsrs r4, r4, \shift
#endif
ldr r3, [r1], #4
#ifdef __ARM_BIG_ENDIAN
lsrs r5, r3, 32-\shift
#else
lsls r5, r3, 32-\shift
#endif
orr r4, r4, r5
str r4, [r0], #4
mov r4, r3
subs r2, #4
bhs 1b
.endm
.Lmisaligned_copy_1_3:
mis_src_copy shift=8
b .Lsrc_misaligned_tail
.Lmisaligned_copy_3_1:
mis_src_copy shift=24
b .Lsrc_misaligned_tail
.Lmisaligned_copy_2_2:
/* For 2_2 misalignment, ldr is still faster than 2 x ldrh. */
mis_src_copy shift=16
.Lsrc_misaligned_tail:
adds r2, #4
subs r1, ip
pop {r4, r5}
#endif /* __ARM_FEATURE_UNALIGNED */
.Lbyte_copy:
subs r2, #4
blo .Lcopy_less_than_4
.Lbyte_copy_loop:
subs r2, #1
ldrb r3, [r1], #1
strb r3, [r0], #1
bhs .Lbyte_copy_loop
ldrb r3, [r1]
strb r3, [r0]
ldrb r3, [r1, #1]
strb r3, [r0, #1]
ldrb r3, [r1, #2]
strb r3, [r0, #2]
#ifdef __ARM_FEATURE_UNALIGNED
mov r0, ip
#else
pop {r0}
#endif
bx lr
.size memcpy, .-memcpy

Some files were not shown because too many files have changed in this diff Show More