rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,11 @@
config AOS_MCU_ASR5501
bool
select AOS_ARCH_ARMV7M
select AOS_COMP_NEWLIB_STUB
select AOS_COMP_RHINO
help
driver & sdk for platform/mcu asr5501
if AOS_MCU_ASR5501
# Configurations for mcu asr5501
endif

View file

@ -0,0 +1,23 @@
## Contents
This is a mcu demo for consuling, not a true realization.
Directory structure:
```
Dir\File Description Necessary for kernel run
============================================================================================
|-- drivers # board peripheral driver Y
|-- hal # hal API layer, hal uart is necessary Y
|-- aos.mk # mcu makefile Y
|-- Config.in # menuconfig component config Y
|-- ucube.py # aos build system file(for scons) N
|-- README.md Y
```
Attention: If there are several mcu types here, use independent sub mk file to put different config.
## Overview
## Resources
## Reference

View file

@ -0,0 +1,13 @@
import sys, hashlib
def MD5(bytes):
md5 = hashlib.md5()
md5.update(bytes)
return md5.hexdigest().decode('hex')
ota_bin = sys.argv[1]
with open(ota_bin, 'rb') as file:
ota_md5_bytes = MD5(file.read())
with open(ota_bin, 'ab') as file:
file.write(ota_md5_bytes)

View file

@ -0,0 +1,84 @@
NAME := mcu_asr5501
HOST_OPENOCD := asr5501
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 1.0.0
$(NAME)_SUMMARY := driver & sdk for platform/mcu asr5501
LWIP := 1
ifeq ($(LWIP),1)
$(NAME)_COMPONENTS += lwip
no_with_lwip := 0
GLOBAL_DEFINES += WITH_LWIP
endif
$(NAME)_COMPONENTS += arch_armv7m
$(NAME)_CFLAGS += -DLEGA_CM4 -DALIOS_SUPPORT -DWIFI_DEVICE -D_SPI_FLASH_ENABLE_ -DPS_CLOSE_APLL -DDCDC_PFMMODE_CLOSE -D_SPI_FLASH_120MHz_ -DCFG_MIMO_UF
$(NAME)_CFLAGS += -DCFG_BATX=1 -DCFG_BARX=1 -DCFG_REORD_BUF=4 -DCFG_SPC=4 -DCFG_TXDESC0=4 -DCFG_TXDESC1=4 -DCFG_TXDESC2=4 -DCFG_TXDESC3=4 -DCFG_TXDESC4=4 -DCFG_CMON -DCFG_MDM_VER_V21 -DCFG_SOFTAP_SUPPORT -DCFG_SNIFFER_SUPPORT -DCFG_DBG=2 -D__FPU_PRESENT=1 -DDX_CC_TEE -DHASH_SHA_512_SUPPORTED -DCC_HW_VERSION=0xF0 -DDLLI_MAX_BUFF_SIZE=0x10000 -DSSI_CONFIG_TRNG_MODE=0
#$(NAME)_CFLAGS += -DXO_FREQ_BIAS_CONFIG
#default a0v2 config
ifeq ($(buildsoc),a0v1)
$(NAME)_CFLAGS += -DLEGA_A0V1
else
$(NAME)_CFLAGS += -DLEGA_A0V2
endif
$(NAME)_CFLAGS += -Wall -Wno-error -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
BINS ?=
GLOBAL_CFLAGS += -mcpu=cortex-m4 -mthumb -mthumb-interwork -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -std=gnu99 -ffunction-sections -fdata-sections
GLOBAL_ASMFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16
GLOBAL_DEFINES += CONFIG_AOS_KV_MULTIPTN_MODE
GLOBAL_DEFINES += CONFIG_AOS_KV_PTN=6
GLOBAL_DEFINES += CONFIG_AOS_KV_SECOND_PTN=7
GLOBAL_DEFINES += CONFIG_AOS_KV_PTN_SIZE=4096
GLOBAL_DEFINES += KV_CONFIG_TOTAL_SIZE=8192
GLOBAL_DEFINES += MBEDTLS_AES_ROM_TABLES
GLOBAL_LDFLAGS += -mcpu=cortex-m4 -mthumb -Wl,-gc-sections
GLOBAL_INCLUDES += drivers/driver/inc \
drivers/platform/CMSIS/Include \
drivers/common \
drivers/platform/misc \
drivers/platform/system/include \
hal/inc \
#soc
$(NAME)_SOURCES += drivers/platform/system/systick_delay.c \
drivers/platform/system/system_cm4.c \
drivers/platform/misc/misc.c \
drivers/common/lega_mac_addr.c
#hal
$(NAME)_SOURCES += hal/src/hw.c \
hal/src/gpio.c \
hal/src/uart.c \
hal/src/flash.c \
hal/src/wdg.c \
hal/src/wifi_port.c \
hal/src/ota.c \
hal/src/pwrmgmt_hal/board_cpu_pwr.c \
hal/src/pwrmgmt_hal/board_cpu_pwr_rtc.c \
hal/src/pwrmgmt_hal/board_cpu_pwr_systick.c
#driver
$(NAME)_SOURCES += drivers/driver/src/lega_flash_alg.c \
drivers/driver/src/lega_efuse.c \
drivers/driver/src/lega_board.c \
drivers/driver/src/lega_flash.c \
drivers/driver/src/lega_gpio.c \
drivers/driver/src/lega_uart.c \
drivers/driver/src/lega_wdg.c \
$(NAME)_PREBUILT_LIBRARY := drivers/libs/$(HOST_ARCH)/libasr_wifi.a

View file

@ -0,0 +1,104 @@
NAME := asr5501
HOST_OPENOCD := asr5501
$(NAME)_TYPE := kernel
$(NAME)_COMPONENTS += platform/arch/arm/armv7m
$(NAME)_COMPONENTS += libc rhino hal netmgr framework.common cjson cli digest_algorithm protocols.net
$(NAME)_CFLAGS += -DLEGA_CM4 -DALIOS_SUPPORT -DWIFI_DEVICE -D_SPI_FLASH_ENABLE_ -DDCDC_PFMMODE_CLOSE -D_SPI_FLASH_120MHz_ -DCFG_MIMO_UF
$(NAME)_CFLAGS += -DCFG_BATX=1 -DCFG_BARX=1 -DCFG_REORD_BUF=4 -DCFG_SPC=4 -DCFG_TXDESC0=4 -DCFG_TXDESC1=4 -DCFG_TXDESC2=4 -DCFG_TXDESC3=4 -DCFG_TXDESC4=4 -DCFG_CMON -DCFG_MDM_VER_V21 -DCFG_SOFTAP_SUPPORT -DCFG_SNIFFER_SUPPORT -DCFG_DBG=2 -D__FPU_PRESENT=1 -DDX_CC_TEE -DHASH_SHA_512_SUPPORTED -DCC_HW_VERSION=0xF0 -DDLLI_MAX_BUFF_SIZE=0x10000 -DSSI_CONFIG_TRNG_MODE=0
$(NAME)_CFLAGS += -DCFG_SNIFFER_UNICAST_SUPPORT
#$(NAME)_CFLAGS += -DXO_FREQ_BIAS_CONFIG
$(NAME)_CFLAGS += -D_LOWER_CCA_THRESHOLD_
ifneq ($(mcu_highfreq),true)
$(NAME)_CFLAGS += -DPS_CLOSE_APLL
endif
#default a0v2 config
ifeq ($(buildsoc),a0v1)
$(NAME)_CFLAGS += -DLEGA_A0V1
else
$(NAME)_CFLAGS += -DLEGA_A0V2
endif
$(NAME)_CFLAGS += -Wall -Wno-error -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
BINS ?=
GLOBAL_CFLAGS += -mcpu=cortex-m4 -mthumb -mthumb-interwork -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -std=gnu99 -ffunction-sections -fdata-sections
GLOBAL_ASMFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=softfp -mfpu=fpv4-sp-d16
GLOBAL_DEFINES += CONFIG_AOS_KV_MULTIPTN_MODE
GLOBAL_DEFINES += CONFIG_AOS_KV_PTN=6
GLOBAL_DEFINES += CONFIG_AOS_KV_SECOND_PTN=7
GLOBAL_DEFINES += CONFIG_AOS_KV_PTN_SIZE=4096
GLOBAL_DEFINES += KV_CONFIG_TOTAL_SIZE=8192
GLOBAL_DEFINES += CONFIG_AOS_KV_BUFFER_SIZE=8192
GLOBAL_DEFINES += CONFIG_AOS_CLI_STACK_SIZE=4096
GLOBAL_DEFINES += MBEDTLS_AES_ROM_TABLES
ifeq ($(wifips),true)
GLOBAL_DEFINES += WIFI_CONFIG_SUPPORT_LOWPOWER=1
endif
ifeq ($(mcu_highfreq),true)
GLOBAL_DEFINES += HIGHFREQ_MCU160_SUPPORT
endif
GLOBAL_LDFLAGS += -mcpu=cortex-m4 -mthumb -Wl,-gc-sections
GLOBAL_INCLUDES += drivers/driver/inc \
drivers/platform/CMSIS/Include \
drivers/common \
drivers/platform/misc \
drivers/platform/system/include \
hal/inc \
../../../framework/uOTA/hal\
../../../framework/uOTA/inc
#soc
$(NAME)_SOURCES += drivers/platform/system/systick_delay.c \
drivers/platform/system/system_cm4.c \
drivers/platform/misc/misc.c \
drivers/common/lega_mac_addr.c
#hal
$(NAME)_SOURCES += hal/src/hw.c \
hal/src/gpio.c \
hal/src/uart.c \
hal/src/flash.c \
hal/src/timer.c \
hal/src/pwm.c \
hal/src/wdg.c \
hal/src/wifi_port.c \
hal/src/pwrmgmt_hal/board_cpu_pwr.c \
hal/src/pwrmgmt_hal/board_cpu_pwr_rtc.c \
hal/src/pwrmgmt_hal/board_cpu_pwr_systick.c
ifeq ($(mcu_highfreq),true)
$(NAME)_PREBUILT_LIBRARY := drivers/libs/$(HOST_ARCH)/mcu_160m/libasr_wifi.a
else
$(NAME)_PREBUILT_LIBRARY := drivers/libs/$(HOST_ARCH)/mcu_52m/libasr_wifi.a
endif
ifeq ($(VENDOR_MXCHIP),1)
$(NAME)_SOURCES += hal/src/ota.c
else
$(NAME)_PREBUILT_LIBRARY += drivers/libs/$(HOST_ARCH)/libota_port.a
endif
#driver
$(NAME)_SOURCES += drivers/driver/src/lega_flash_alg.c \
drivers/driver/src/lega_efuse.c \
drivers/driver/src/lega_board.c \
drivers/driver/src/lega_flash.c \
drivers/driver/src/lega_gpio.c \
drivers/driver/src/lega_uart.c \
drivers/driver/src/lega_wdg.c \
drivers/driver/src/lega_pwm.c \
drivers/driver/src/lega_timer.c

View file

@ -0,0 +1,18 @@
#ifndef _LEGA_COMM_H_
#define _LEGA_COMM_H_
void jumpToApp(int addr);
void lega_memset(char *buf,int value, int size);
void lega_memcpy(char *dst, char *src, int size);
void delay(unsigned int cycles);
int convert_str_to_int(char *str);
void convert_int_to_str(unsigned int val, unsigned int type, char *ch);
/// Macro to read a register
#define REG_RD(addr) (*(volatile uint32_t *)(addr))
/// Macro to write a register
#define REG_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value)
void lega_write32_bit(uint32_t reg, uint8_t start_bit, uint8_t len, uint32_t src_val);
uint32_t lega_read32_bit(uint32_t reg, uint8_t start_bit, uint8_t len);
#endif //_LEGA_COMM_H_

View file

@ -0,0 +1,42 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef ALIOS_SUPPORT
#include "lega_rhino.h"
#else
#include "lega_rtos_api.h"
#endif
#include "lega_common.h"
int get_random_int_c()
{
int i;
srand(lega_rtos_get_time());
i = rand();
return i;
}
/**
* @brief if no mac address burned in efuse memory,
* user could modify this function to set default mac address
*
* @param mac_addr : mac_addr pointer wifi stack used
*/
void lega_wlan_default_mac_addr(uint8_t *mac_addr)
{
mac_addr[0] = 0xAA;
mac_addr[1] = 0x00;
mac_addr[2] = 0xCC;
mac_addr[3] = (uint8_t)((get_random_int_c()>>16)&0xff);
mac_addr[4] = (uint8_t)((get_random_int_c()>>8)&0xff);
mac_addr[5] = (uint8_t)((get_random_int_c()>>0)&0xff);
}
void lega_rf_set_xo_freq_bias(void)
{
#ifdef XO_FREQ_BIAS_CONFIG
//XO freq bias for blue board
REG_WR(0x40000A74, 0x9191);
#endif
printf("Current xo config is 0x%x\r\n",(unsigned int)REG_RD(0x40000A74));
}

View file

@ -0,0 +1,114 @@
#ifndef _LEGA_ADC_H_
#define _LEGA_ADC_H_
#define ADC_ENABLE
#if defined ADC_ENABLE
#define SYS_REG_BASE 0x40000000
#define SYS_REG_BASE_CORE_CLK ((SYS_REG_BASE + 0x804))
#define SYS_REG_BASE_FLASH_SEL_CLK ((SYS_REG_BASE + 0x808))
#define SYS_REG_BASE_MAC_CORE_CLK ((SYS_REG_BASE + 0x810))
#define SYS_REG_BASE_REF_ROOT_CLK ((SYS_REG_BASE + 0x80C))
#define SYS_REG_BASE_WIFI_CLK ((SYS_REG_BASE + 0x85C))
#define SYS_REG_BASE_DIG32_SEL ((SYS_REG_BASE + 0x908))
#define SYS_REG_BASE_PMU_CTRL ((SYS_REG_BASE + 0xA20))
#define SYS_REG_BASE_AUXADC ((SYS_REG_BASE + 0x19000))
#define SYS_REG_DCDC_REG3 (SYS_REG_BASE + 0xA50)
#define SYS_REG_BASE_XOCTRL2 ((SYS_REG_BASE + 0xA70))
#define SYS_REG_BASE_XODCCA_CTRL ((SYS_REG_BASE + 0xA74))
#define BIT(pos) (1U<<(pos))
/* Modem Config */
#define MDM_MEMCLKCTRL0_ADDR 0x60C00848
#define MDM_CLKGATEFCTRL0_ADDR 0x60C00874
#define RIU_AGCMEMBISTSTAT_ADDR 0x60C0B238
#define RC_SW_CTRL_ADDR 0x60C0C004
#define SPI_COMMAND RC_SW_CTRL_ADDR
#define SPI_RDATA RC_SW_CTRL_ADDR
#define ASSERT_ERR(cond) \
do{}while(0)
/// Length of a char in bytes
#define CHAR_LEN 1 //(CHAR_BIT/8)
/**
****************************************************************************************
* @brief Converts a CPU pointer into a HW address
* This macro is used to convert a SW pointer into the corresponding HW address. With CPUs
* having native byte support, the value returned will be the same as the pointer passed.
* With TL4, the value returned is the pointer multiplied by 2.
* @param[in] ptr Pointer to be converted
* @return The corresponding HW address
****************************************************************************************
*/
#define CPU2HW(ptr) (((uint32_t)(ptr)) * CHAR_LEN)
/**
****************************************************************************************
* @brief Converts a HW address into a CPU pointer
* This macro is doing the reverse operation as @ref CPU2HW.
* @param[in] ptr Address to be converted
* @return The corresponding CPU pointer
****************************************************************************************
*/
#define HW2CPU(ptr) ((void *)(((uint32_t)(ptr)) / CHAR_LEN))
/*
* MACROS
****************************************************************************************
*/
/// Macro to read a platform register
#define REG_PL_RD(addr) (*(volatile uint32_t *)(HW2CPU(addr)))
/// Macro to write a platform register
#define REG_PL_WR(addr, value) (*(volatile uint32_t *)(HW2CPU(addr))) = (value)
typedef enum
{
ADC_CHANNEL_NUM0,
ADC_CHANNEL_NUM1,
ADC_CHANNEL_NUM2,
ADC_CHANNEL_NUM3,
ADC_CHANNEL_NUM4,
ADC_CHANNEL_NUM5,
ADC_CHANNEL_NUM6,
ADC_CHANNEL_NUM7,
}lega_adc_channel_t;
typedef struct {
uint32_t sampling_cycle; /* sampling period in number of ADC clock cycles */
}lega_adc_config_t;
typedef struct {
uint8_t port; /* adc port */
lega_adc_config_t config; /* adc config */
void *priv; /* priv data */
}lega_adc_dev_t;
extern uint16_t spi_mst_read(uint16_t addr);
extern void spi_mst_write(uint16_t addr, uint16_t data);
/**
* founction for adc sample
* channnel pin which is set to adc sample.
* reference voltage 1.6V ADC resolution 12bit
* @param[in] channnel pin which is set to adc sample:rang0-7 (pad4-11)
*
* @return value:adc sample data rang:0-4095, -1: if an error occurred with any step
*/
int32_t lega_adc_get(lega_adc_dev_t *adc_config);
#endif
#endif //_LEGA_ADC_H_

View file

@ -0,0 +1,13 @@
#ifndef _LEGA_BOOT_H_
#define _LEGA_BOOT_H_
#define AON_RST_CHECK_REG (ALWAYS_ON_REGFILE + 0x10)
#define AON_RST_CHECK_FLAG 0x00000002
#define LEGA_AON_POWER_ON_FLAG 0x12345678
#define PWR_ON_RST 0
#define HARDWARE_PIN_RST 1
#define SOFTWARE_RST 2 //including NVIC_SystemReset and WDG RST
uint8_t lega_get_boot_type(void);
#endif //_LEGA_BOOT_H_

View file

@ -0,0 +1,202 @@
#ifndef _LEGA_DMA_H_
#define _LEGA_DMA_H_
#include <stdint.h>
//#include "core_cm4.h"
//#include "core_cm4_simd.h"
//#include "core_cmFunc.h"
//#include "core_cmInstr.h"
// DRAMC Registers
#define DMA_BASE 0x40004000
#define DMA_CLOCK_BASE 0x40000950
// ch0
#define DMA_SAR0_L *((volatile int *)(DMA_BASE+0x000))
#define DMA_SAR0_H *((volatile int *)(DMA_BASE+0x004))
#define DMA_DAR0_L *((volatile int *)(DMA_BASE+0x008))
#define DMA_DAR0_H *((volatile int *)(DMA_BASE+0x00C))
#define DMA_LLP0_L *((volatile int *)(DMA_BASE+0x010))
#define DMA_LLP0_L_REG (DMA_BASE+0x010)
#define DMA_LLP0_H *((volatile int *)(DMA_BASE+0x014))
#define DMA_CTL0_L *((volatile int *)(DMA_BASE+0x018))
#define DMA_CTL0_L_REG (DMA_BASE+0x018)
#define DMA_CTL0_H *((volatile int *)(DMA_BASE+0x01C))
#define DMA_CTL0_H_REG (DMA_BASE+0x01C)
#define DMA_SSTAT0_L *((volatile int *)(DMA_BASE+0x020))
#define DMA_SSTAT0_H *((volatile int *)(DMA_BASE+0x024))
#define DMA_DSTAT0_L *((volatile int *)(DMA_BASE+0x028))
#define DMA_DSTAT0_H *((volatile int *)(DMA_BASE+0x02C))
#define DMA_SSTATAR0_L *((volatile int *)(DMA_BASE+0x030))
#define DMA_SSTATAR0_H *((volatile int *)(DMA_BASE+0x034))
#define DMA_DSTATAR0_L *((volatile int *)(DMA_BASE+0x038))
#define DMA_DSTATAR0_H *((volatile int *)(DMA_BASE+0x03C))
#define DMA_CFG0_L *((volatile int *)(DMA_BASE+0x040))
#define DMA_CFG0_L_REG (DMA_BASE+0x040)
#define DMA_CFG0_H *((volatile int *)(DMA_BASE+0x044))
#define DMA_CFG0_H_REG (DMA_BASE+0x044)
#define DMA_SGR0_L *((volatile int *)(DMA_BASE+0x048))
#define DMA_SGR0_H *((volatile int *)(DMA_BASE+0x04C))
#define DMA_DSR0_L *((volatile int *)(DMA_BASE+0x050))
#define DMA_DSR0_H *((volatile int *)(DMA_BASE+0x054))
// ch1
#define DMA_SAR1_L *((volatile int *)(DMA_BASE+0x058))
#define DMA_SAR1_H *((volatile int *)(DMA_BASE+0x05C))
#define DMA_DAR1_L *((volatile int *)(DMA_BASE+0x060))
#define DMA_DAR1_H *((volatile int *)(DMA_BASE+0x064))
#define DMA_LLP1_L *((volatile int *)(DMA_BASE+0x068))
#define DMA_LLP1_H *((volatile int *)(DMA_BASE+0x06C))
#define DMA_CTL1_L *((volatile int *)(DMA_BASE+0x070))
#define DMA_CTL1_L_REG (DMA_BASE+0x070)
#define DMA_CTL1_H *((volatile int *)(DMA_BASE+0x074))
#define DMA_SSTAT1_L *((volatile int *)(DMA_BASE+0x078))
#define DMA_SSTAT1_H *((volatile int *)(DMA_BASE+0x07C))
#define DMA_DSTAT1_L *((volatile int *)(DMA_BASE+0x080))
#define DMA_DSTAT1_H *((volatile int *)(DMA_BASE+0x084))
#define DMA_SSTATAR1_L *((volatile int *)(DMA_BASE+0x088))
#define DMA_SSTATAR1_H *((volatile int *)(DMA_BASE+0x08C))
#define DMA_DSTATAR1_L *((volatile int *)(DMA_BASE+0x090))
#define DMA_DSTATAR1_H *((volatile int *)(DMA_BASE+0x094))
#define DMA_CFG1_L *((volatile int *)(DMA_BASE+0x098))
#define DMA_CFG1_L_REG (DMA_BASE+0x098)
#define DMA_CFG1_H *((volatile int *)(DMA_BASE+0x09C))
#define DMA_CFG1_H_REG (DMA_BASE+0x09C)
#define DMA_SGR1_L *((volatile int *)(DMA_BASE+0x0A0))
#define DMA_SGR1_H *((volatile int *)(DMA_BASE+0x0A4))
#define DMA_DSR1_L *((volatile int *)(DMA_BASE+0x0A8))
#define DMA_DSR1_H *((volatile int *)(DMA_BASE+0x0AC))
#define DMACFGREG_L *((volatile int *)(DMA_BASE+0x398))
#define DMACFGREG_H *((volatile int *)(DMA_BASE+0x39C))
#define CHENREG_L *((volatile int *)(DMA_BASE+0x3A0))
#define CHENREG_L_REG (DMA_BASE+0x3A0)
#define CHENREG_H *((volatile int *)(DMA_BASE+0x3A4))
#define DMA_COMP_PARAMS_3_L *((volatile int *)(DMA_BASE+0x3E0))
#define DMA_COMP_PARAMS_3_H *((volatile int *)(DMA_BASE+0x3E4))
#define DMA_COMP_PARAMS_2_L *((volatile int *)(DMA_BASE+0x3E8))
#define DMA_COMP_PARAMS_2_H *((volatile int *)(DMA_BASE+0x3EC))
#define DMA_COMP_PARAMS_1_L *((volatile int *)(DMA_BASE+0x3F0))
#define DMA_COMP_PARAMS_1_H *((volatile int *)(DMA_BASE+0x3F4))
//DMA interrupt registers
#define DMA_RAW_TFR_L_REG (DMA_BASE+0x2C0)
#define DMA_RAW_TFR_H_REG (DMA_BASE+0x2C4)
#define DMA_RAW_BLOCK_L_REG (DMA_BASE+0x2C8)
#define DMA_RAW_BLOCK_H_REG (DMA_BASE+0x2CC)
#define DMA_STATUS_TFR_L_REG (DMA_BASE+0x2E8)
#define DMA_STATUS_TFR_H_REG (DMA_BASE+0x2EC)
#define DMA_STATUS_BLOCK_L_REG (DMA_BASE+0x2F0)
#define DMA_STATUS_BLOCK_H_REG (DMA_BASE+0x2F4)
#define DMA_MASK_TFR_L_REG (DMA_BASE+0x310)
#define DMA_MASK_TFR_H_REG (DMA_BASE+0x314)
#define DMA_MASK_BLOCK_L_REG (DMA_BASE+0x318)
#define DMA_MASK_BLOCK_H_REG (DMA_BASE+0x31C)
#define DMA_CLEAR_TFR_L_REG (DMA_BASE+0x338)
#define DMA_CLEAR_TFR_H_REG (DMA_BASE+0x33C)
#define DMA_CLEAR_BLOCK_L_REG (DMA_BASE+0x340)
#define DMA_CLEAR_BLOCK_H_REG (DMA_BASE+0x344)
#define DMA_STATUS_INT_REG (DMA_BASE+0x360)
#define LEGA_DMA_NUM 2
typedef void (*lega_dma_callback_func)(char);
/*
* DMA mode
*/
typedef enum {
M2M_MODE,
M2P_MODE,
P2M_MODE,
P2P_MODE
} lega_dma_mode_t;
/*
* DMA HW handshake
*/
typedef enum {
UART0_TX_HS,
UART0_RX_HS,
UART1_TX_HS,
UART1_RX_HS,
UART2_TX_HS,
UART2_RX_HS,
SPI0_TX_HS,
SPI0_RX_HS,
SPI1_TX_HS,
SPI1_RX_HS,
SPI2_TX_HS,
SPI2_RX_HS,
I2C0_TX_HS,
I2C0_RX_HS,
I2C1_TX_HS,
I2C1_RX_HS,
} lega_dma_hs_t;
typedef struct{
uint32_t * DMA_SAR_L;
uint32_t * DMA_DAR_L;
uint32_t * DMA_LLP_L;
uint32_t * DMA_LLP_H;
uint32_t * DMA_CTL_H;
uint32_t * DMA_CFG_L;
uint32_t DMA_CTL_L_REG;
uint32_t DMA_CFG_H_REG;
} lega_dma_config_reg_t;
/*
* DMA configuration
*/
typedef struct {
uint32_t src; //src
uint32_t dest; //dst
uint8_t ch; //channel
lega_dma_mode_t mode; //mode
void *priv; /* priv data */
} lega_dma_dev_t;
/**
* Initialises a dma interface
*
*
* @param[in] dma the interface which should be initialised
*
* @return
*/
void lega_dma_init(lega_dma_dev_t *dma);
/**
* Transmit data on a dma interface
*
* @param[in] dma the dma interface
* @param[in] size number of bytes to transmit
*
* @return
*/
void lega_dma_send(lega_dma_dev_t *dma,/*const void *data,*/ uint32_t size, uint32_t timeout);
/**
* Deinitialises a dma interface
*
* @param[in] DMA the interface which should be deinitialised
*
* @return
*/
void lega_dma_finalize(lega_dma_dev_t *dma);
#endif // _LEGA_DMA_H_

View file

@ -0,0 +1,23 @@
#ifndef _LEGA_EFUSE_H_
#define _LEGA_EFUSE_H_
#define EFUSE_READ_OP_WAIT_CYCLE 5
#define EFUSE_WRITE_OP_WAIT_CYCLE (SYSTEM_CLOCK/100000*2) //10us
#define EFUSE_DIV_OP_WAIT_CYCLE 31
#define EFUSE_LDO25_OPEN 1
#define EFUSE_LDO25_CLOSE 0
void lega_efuse_init(uint8_t ldo25_open);
uint8_t lega_efuse_byte_read(uint16_t addr);
uint32_t lega_efuse_word_read(uint16_t addr);
void lega_efuse_byte_write(uint16_t addr, uint8_t data);
void lega_efuse_word_write(uint16_t addr, uint32_t data);
void lega_efuse_multi_read(uint16_t start_addr, uint16_t size_in_bytes, uint8_t *pData);
#endif //_LEGA_EFUSE_H_

View file

@ -0,0 +1,165 @@
#ifndef _LEGA_FLASH_H_
#define _LEGA_FLASH_H_
#include <stdint.h>
#define PAR_OPT_READ_POS ( 0 )
#define PAR_OPT_WRITE_POS ( 1 )
#define PAR_OPT_READ_MASK ( 0x1u << PAR_OPT_READ_POS )
#define PAR_OPT_WRITE_MASK ( 0x1u << PAR_OPT_WRITE_POS )
#define PAR_OPT_READ_DIS ( 0x0u << PAR_OPT_READ_POS )
#define PAR_OPT_READ_EN ( 0x1u << PAR_OPT_READ_POS )
#define PAR_OPT_WRITE_DIS ( 0x0u << PAR_OPT_WRITE_POS )
#define PAR_OPT_WRITE_EN ( 0x1u << PAR_OPT_WRITE_POS )
typedef enum {
PARTITION_ERROR = -1,
PARTITION_BOOTLOADER,
PARTITION_APPLICATION,
PARTITION_ATE,
PARTITION_OTA_TEMP,
PARTITION_RF_FIRMWARE,
PARTITION_PARAMETER_1,
PARTITION_PARAMETER_2,
PARTITION_PARAMETER_3,
PARTITION_PARAMETER_4,
PARTITION_BT_FIRMWARE,
PARTITION_SPIFFS,
PARTITION_CUSTOM_1,
PARTITION_CUSTOM_2,
PARTITION_RECOVERY,
PARTITION_MAX,
PARTITION_NONE,
} lega_partition_t;
typedef enum {
FLASH_EMBEDDED,
FLASH_SPI,
FLASH_QSPI,
FLASH_MAX,
FLASH_NONE,
} lega_flash_t;
typedef struct {
lega_flash_t partition_owner;
const char *partition_description;
uint32_t partition_start_addr;
uint32_t partition_length;
uint32_t partition_options;
} lega_logic_partition_t;
/**
* lega flash init
*
* @note this function must be called before flash erase/write operation
* also, this function must not be interrupted, it should be called
* with interrupt disabled
* @param[in] none
*
* @return HAL_logi_partition struct
*/
int32_t lega_flash_init(void);
/**
* Get the infomation of the specified flash area
*
* @param[in] in_partition The target flash logical partition
*
* @return HAL_logi_partition struct
*/
lega_logic_partition_t *lega_flash_get_info(lega_partition_t in_partition);
/**
* Erase an area on a Flash logical partition
*
* @note Erase on an address will erase all data on a sector that the
* address is belonged to, this function does not save data that
* beyond the address area but in the affected sector, the data
* will be lost.
*
* @param[in] in_partition The target flash logical partition which should be erased
* @param[in] off_set Start address of the erased flash area
* @param[in] size Size of the erased flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_erase(lega_partition_t in_partition, uint32_t off_set, uint32_t size);
/**
* Write data to an area on a flash logical partition without erase
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_write(lega_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len);
/**
* Write data to an area on a flash logical partition with erase first
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_erase_write(lega_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len);
/**
* Read data from an area on a Flash to data buffer in RAM
*
* @param[in] in_partition The target flash logical partition which should be read
* @param[in] off_set Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] outBuffer Point to the data buffer that stores the data read from flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_read(lega_partition_t in_partition, uint32_t *off_set,
void *out_buf, uint32_t in_buf_len);
/**
* Set security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of enabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_enable_secure(lega_partition_t partition, uint32_t off_set, uint32_t size);
/**
* Disable security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of disabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_dis_secure(lega_partition_t partition, uint32_t off_set, uint32_t size);
#endif //_LEGA_FLASH_H_

View file

@ -0,0 +1,219 @@
/* -----------------------------------------------------------------------------
* Copyright (c) 2014 ARM Ltd.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software. Permission is granted to anyone to use this
* software for any purpose, including commercial applications, and to alter
* it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
*
* $Date: 14. Jan 2014
* $Revision: V1.00
*
* Project: FlashOS Headerfile for Flash drivers
* --------------------------------------------------------------------------- */
/* History:
* Version 1.00
* Initial release
*/
#ifndef _LEGA_FLASH_ALG_H_
#define _LEGA_FLASH_ALG_H_
typedef volatile unsigned char vu8;
typedef volatile unsigned long vu32;
typedef volatile unsigned short vu16;
#define M8(adr) (*((vu8 *) (adr)))
#define M16(adr) (*((vu16 *) (adr)))
#define M32(adr) (*((vu32 *) (adr)))
// Peripheral Memory Map
#define FLASH_BASE 0x40003000
#define PP 0x02
#define QPP 0x32
#define PP4 0x38
#define WREN 0x06
#define SE 0x20
#define BE 0xD8
#define BE32K 0x52
#define CE 0xC7
#define EQPI 0x35
#define RSTEN 0x66
#define RST 0x99
#define READ 0x03
#define F_RD 0x0B
#define DREAD 0x3B
#define QREAD 0x6B
#define READ2 0xBB
#define READ4 0xEB
#define RDID 0x9F
#define WRSR 0x01
#define RDSR 0x05
#define RDSR1 0x35
#define OSC (100)
#define OSC_D ((OSC*144)/8)
#if (defined LEGA_A0V1)
typedef struct {
vu32 CMD ; //offset 0x00
vu32 LENGTH ; //offset 0x04
vu32 ADDR ; //offset 0x08
vu32 TX_DATA ; //offset 0x0C
vu32 DUMMY ; //offset 0x10
vu32 SBUS_START ; //offset 0x14
vu32 ID ; //offset 0x18
vu32 STATUS ; //offset 0x1C
vu32 SEC_STATUS ; //offset 0x20
vu32 ENHANCE ; //offset 0x24
vu32 QPI_MODE ; //offset 0x28
vu32 DP_STATUS ; //offset 0x2C
vu32 ERROR_INT_EN; //offset 0x30
vu32 ERROR_INT ; //offset 0x34
vu32 ERROR_TYPE ; //offset 0x38
vu32 PENDING ; //offset 0x3C
vu32 BUSY ; //offset 0x40
vu32 DONE_INT_EN ; //offset 0x44
vu32 DONE_INT ; //offset 0x48
vu32 DONE_STATUS ; //offset 0x4C
vu32 CFG ; //offset 0x50
vu32 CLK_DIV ; //offset 0x54
vu32 RX_DATA ; //offset 0x58
vu32 CACHE_CNT_EN; //offset 0x5C
vu32 CNT_HIT0 ; //offset 0x60
vu32 CNT_HIT1 ; //offset 0x64
vu32 CNT_MISS ; //offset 0x68
vu32 IBUS_CMD ; //offset 0x6C
} FLASH_TypeDef;
#elif (defined LEGA_A0V2)
typedef struct {
vu32 QSPI_CR ; //offset 0x00
vu32 QSPI_DCR ; //offset 0x04
vu32 QSPI_SR ; //offset 0x08
vu32 QSPI_FCR ; //offset 0x0C
vu32 QSPI_DLR ; //offset 0x10
vu32 QSPI_CCR ; //offset 0x14
vu32 QSPI_AR ; //offset 0x18
vu32 QSPI_ABR ; //offset 0x1C
vu32 QSPI_DR ; //offset 0x20
vu32 QSPI_PSMKR ; //offset 0x24
vu32 QSPI_PSMAR ; //offset 0x28
vu32 QSPI_PIR ; //offset 0x2C
vu32 QSPI_TOR ; //offset 0x30
vu32 RESERVERD[19];
vu32 QSPI_HIT0R ; //offset 0x80
vu32 QSPI_HIT1R ; //offset 0x84
vu32 QSPI_MIR ; //offset 0x88
vu32 QSPI_CFGR ; //offset 0x8C
vu32 SBUS_START ; //offset 0x90
} FLASH_TypeDef;
#endif
#define NVM_CTRL_WR_LOCK *((volatile unsigned int *)(0x40000A04))
#define FLASH_ACCESS_CONTROL0 *((volatile unsigned int *)(0x40000A08))
#define FLASH_ACCESS_CONTROL1 *((volatile unsigned int *)(0x40000A0C))
#if (defined LEGA_A0V1)
#define FLASH_CACHE_CTRL *((volatile unsigned int *)(0x40021000))
#elif (defined LEGA_A0V2)
#define FLASH_CACHE_CTRL *((volatile unsigned int *)(0x4001C000))
#endif
#define CACHE_BYPASS (1 << 1)
#define CACHE_FLUSH (1)
#define FLASH ((FLASH_TypeDef*) FLASH_BASE)
#define VERS 1 // Interface Version 1.01
#define UNKNOWN 0 // Unknown
#define ONCHIP 1 // On-chip Flash Memory
#define EXT8BIT 2 // External Flash Device on 8-bit Bus
#define EXT16BIT 3 // External Flash Device on 16-bit Bus
#define EXT32BIT 4 // External Flash Device on 32-bit Bus
#define EXTSPI 5 // External Flash Device on SPI
#define SPI_FLASH_SEC_SIZE 0x1000
#define SPI_FLASH_PAGE_SIZE 0x100
#define SECTOR_NUM 512 // Max Number of Sector Items
#define PAGE_MAX 65536 // Max Page Size for Programming
#define CLK_FLASH_SEL 0x40000808
#define FLASH_52_CLK 0x0 //flash clk src 52MHz
#define FLASH_120_CLK 0x1 //flash clk src 120MHz
#define FLASH_240_CLK 0x2 //flash clk src 240MHz
#define FLASH_QSPI_DIV4 0x09004801
#define FLASH_QSPI_DIV3 0x89004801
#define FLASH_QSPI_DIV2 0x08004801
#define FLASH_QSPI_L1 0x2D1C250B
#define FLASH_QSPI_L2 0x4E1C253B
#define FLASH_QSPI_L4 0x6F0CEDEB
#define CHIP_ERASE_CMD 0x0000160
#define SECTOR_ERASE_CMD 0x0002520
#define BLOCK32_ERASE_CMD 0x0002552
#define BLOCK64_ERASE_CMD 0x00025D8
struct FlashSectors {
unsigned long szSector; // Sector Size in Bytes
unsigned long AddrSector; // Address of Sector
};
#define SECTOR_END 0xFFFFFFFF, 0xFFFFFFFF
struct FlashDevice {
unsigned short Vers; // Version Number and Architecture
char DevName[128]; // Device Name and Description
unsigned short DevType; // Device Type: ONCHIP, EXT8BIT, EXT16BIT, ...
unsigned long DevAdr; // Default Device Start Address
unsigned long szDev; // Total Size of Device
unsigned long szPage; // Programming Page Size
unsigned long szSector;
unsigned long Res; // Reserved for future Extension
unsigned char valEmpty; // Content of Erased Memory
unsigned long toProg; // Time Out of Program Page Function
unsigned long toErase; // Time Out of Erase Sector Function
struct FlashSectors sectors[SECTOR_NUM];
};
#define FLASH_DRV_VERS (0x0100+VERS) // Driver Version, do not modify!
#define FLASH_DRIVER_SEG __attribute__((section("seg_flash_driver")))
extern void lega_flash_alg_read_buf_clr(void);
extern void lega_flash_alg_cache_bypass(void);
extern void lega_flash_alg_cache_enable(void);
extern void lega_flash_alg_cache_flush(void);
extern int lega_flash_alg_init (void);
extern int lega_flash_alg_erase(unsigned int cmd, unsigned long adr);
extern int lega_flash_alg_programpage (unsigned long adr, // Program Page Function
unsigned long sz,
unsigned char *buf);
#ifdef _SPI_FLASH_240MHz_
extern void lega_flash_alg_calibrate_shift(int prescaler);
#endif
#ifdef _SPI_FLASH_120MHz_
extern void lega_flash_alg_set_clk_120(unsigned char en_120m);
#endif
#endif //_LEGA_FLASH_ALG_H_

View file

@ -0,0 +1,188 @@
#ifndef _LEGA_GPIO_H_
#define _LEGA_GPIO_H_
#include <stdint.h>
#define GPIO0_INDEX 0
#define GPIO1_INDEX 1
#define GPIO2_INDEX 2
#define GPIO3_INDEX 3
#define GPIO4_INDEX 4
#define GPIO5_INDEX 5
#define GPIO6_INDEX 6
#define GPIO7_INDEX 7
#define GPIO8_INDEX 8
#define GPIO9_INDEX 9
#define GPIO10_INDEX 10
#define GPIO11_INDEX 11
#define GPIO12_INDEX 12
#define GPIO13_INDEX 13
#define GPIO14_INDEX 14
#define GPIO15_INDEX 15
#define GPIO16_INDEX 16
#define GPIO17_INDEX 17
#define GPIO18_INDEX 18
#define GPIO19_INDEX 19
#define GPIO20_INDEX 20
#define GPIO21_INDEX 21
#define GPIO22_INDEX 22
#define GPIO23_INDEX 23
#define GPIO24_INDEX 24
#define GPIO25_INDEX 25
#define GPIO26_INDEX 26
#define GPIO27_INDEX 27
#define GPIO28_INDEX 28
#define GPIO29_INDEX 29
#define GPIO30_INDEX 30
#define GPIO31_INDEX 31
#define LEGA_GPIO_NUM_PER_GROUP 16
#if (defined LEGA_A0V1)
#define LEGA_GPIO_TOTAL_NUM 32
#elif (defined LEGA_A0V2)
#define LEGA_GPIO_TOTAL_NUM 24
#endif
/*
* Pin configuration
*/
typedef enum {
LEGA_ANALOG_MODE, /* Used as a function pin, input and output analog */
LEGA_IRQ_MODE, /* Used to trigger interrupt */
LEGA_INPUT_PULL_UP, /* Input, with an internal pull-up resistor */
LEGA_INPUT_PULL_DOWN, /* Input, with an internal pull-down resistor */
LEGA_INPUT_HIGH_IMPEDANCE, /* Input, must always be driven, either actively or by an external pullup resistor */
LEGA_OUTPUT_PUSH_PULL, /* Output, actively driven high and actively driven low */
LEGA_OUTPUT_OPEN_DRAIN_NO_PULL, /* Output, actively driven low. When set high, is high-impedance */
LEGA_OUTPUT_OPEN_DRAIN_PULL_UP, /* Output, actively driven low. When set high, is pulled high with an internal resistor */
} lega_gpio_config_t;
/*
* GPIO dev struct
*/
typedef struct {
uint8_t port; /* gpio port */
lega_gpio_config_t config; /* gpio config */
void *priv; /* priv data */
} lega_gpio_dev_t;
/*
* GPIO interrupt trigger
*/
typedef enum {
LEGA_IRQ_TRIGGER_RISING_EDGE = 0x1, /* Interrupt triggered at input signal's rising edge */
LEGA_IRQ_TRIGGER_FALLING_EDGE = 0x2, /* Interrupt triggered at input signal's falling edge */
LEGA_IRQ_TRIGGER_BOTH_EDGES = LEGA_IRQ_TRIGGER_RISING_EDGE | LEGA_IRQ_TRIGGER_FALLING_EDGE,
} lega_gpio_irq_trigger_t;
/*
* GPIO interrupt callback handler
*/
typedef void (*lega_gpio_irq_handler_t)(void *arg);
typedef struct {
lega_gpio_irq_handler_t cb;
void *arg;
} lega_gpio_cb_t;
/**
* Initialises a GPIO pin
*
* @note Prepares a GPIO pin for use.
*
* @param[in] gpio the gpio pin which should be initialised
* @param[in] configuration A structure containing the required gpio configuration
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_init(lega_gpio_dev_t *gpio);
/**
* Sets an output GPIO pin high
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set high
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_high(lega_gpio_dev_t *gpio);
/**
* Sets an output GPIO pin low
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_low(lega_gpio_dev_t *gpio);
/**
* Trigger an output GPIO pin's output. Using this function on a
* gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_toggle(lega_gpio_dev_t *gpio);
/**
* Get the state of an input GPIO pin. Using this function on a
* gpio pin which is set to output mode will return an undefined value.
*
* @param[in] gpio the gpio pin which should be read
* @param[in] value gpio value
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_input_get(lega_gpio_dev_t *gpio, uint32_t *value);
/**
* Enables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which is set to
* output mode is undefined.
*
* @param[in] gpio the gpio pin which will provide the interrupt trigger
* @param[in] trigger the type of trigger (rising/falling edge)
* @param[in] handler a function pointer to the interrupt handler
* @param[in] arg an argument that will be passed to the interrupt handler
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_enable_irq(lega_gpio_dev_t *gpio, lega_gpio_irq_trigger_t trigger,
lega_gpio_irq_handler_t handler, void *arg);
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref lega_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_disable_irq(lega_gpio_dev_t *gpio);
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref lega_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_clear_irq(lega_gpio_dev_t *gpio);
/**
* Set a GPIO pin in default state.
*
* @param[in] gpio the gpio pin which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_finalize(lega_gpio_dev_t *gpio);
#endif //_LEGA_GPIO_H_

View file

@ -0,0 +1,134 @@
#ifndef _LEGA_I2C_H_
#define _LEGA_I2C_H_
#include <stdint.h>
#define I2C_DEVICE0 0
#define I2C_DEVICE1 1
#define LEGA_I2C_NUM 2
#define I2C_ADDR_WIDTH_7BIT 7
#define I2C_ADDR_WIDTH_10BIT 10
#define I2C_SS_MAX_SCL_FREQ 100000 //100K
#define I2C_FS_MAX_SCL_FREQ 400000 //400K
#define I2C_FS_PLUS_MAX_SCL_FREQ 1000000 //1M
#define I2C_HS_MAX_SCL_FREQ 3400000 //3.4M
#define I2C_FIFO_DEPTH 32
#define I2C_BUF_QUEUE_SIZE I2C_FIFO_DEPTH //byte
#define I2C_MODE_MASTER 1 /* i2c communication is master mode */
#define I2C_MODE_SLAVE 2 /* i2c communication is slave mode */
#define I2C_MEM_ADDR_SIZE_8BIT 1 /* i2c menory address size 8bit */
#define I2C_MEM_ADDR_SIZE_16BIT 2 /* i2c menory address size 16bit */
typedef void (*lega_i2c_slv_tx_callback_func)(void);
typedef void (*lega_i2c_slv_rx_callback_func)(uint8_t);
typedef struct
{
lega_i2c_slv_tx_callback_func tx_func;
lega_i2c_slv_rx_callback_func rx_func;
}lega_i2c_slv_callback_t;
typedef struct {
uint32_t address_width;
uint32_t freq;
uint8_t mode;
uint16_t dev_addr;
} lega_i2c_config_t;
typedef struct {
uint8_t port; /* i2c port */
lega_i2c_config_t config; /* i2c config */
void *priv; /* priv data */
} lega_i2c_dev_t;
int32_t lega_i2c_reset(lega_i2c_dev_t *i2c);
/**
* Initialises an I2C interface
* Prepares an I2C hardware interface for communication as a master or slave
*
* @param[in] i2c the device for which the i2c port should be initialised
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_init(lega_i2c_dev_t *i2c);
/**
* I2c master send
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] data i2c send data
* @param[in] size i2c send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_master_send(lega_i2c_dev_t *i2c, uint16_t dev_addr, const uint8_t *data,
uint16_t size, uint32_t timeout);
/**
* I2c master recv
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[out] data i2c receive data
* @param[in] size i2c receive data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_master_recv(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint8_t *data,
uint16_t size, uint32_t timeout);
/**
* I2c mem write
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[in] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_mem_write(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, const uint8_t *data, uint16_t size,
uint32_t timeout);
/**
* I2c master mem read
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[out] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_mem_read(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, uint8_t *data, uint16_t size,
uint32_t timeout);
int32_t lega_i2c_tx_data(lega_i2c_dev_t *i2c, uint8_t data);
/**
* Deinitialises an I2C device
*
* @param[in] i2c the i2c device
*
* @return 0 : on success, EIO : if an error occurred during deinitialisation
*/
int32_t lega_i2c_finalize(lega_i2c_dev_t *i2c);
#endif //_LEGA_I2C_H_

View file

@ -0,0 +1,753 @@
#ifndef _LEGA_PERIPHERAL_REG_H_
#define _LEGA_PERIPHERAL_REG_H_
#include <stdint.h>
/*
LEGA GPIO BEGIN
*/
struct LEGA_GPIO
{
__IO uint32_t DATA;
__IO uint32_t DATAOUT;
__I uint32_t DUMMY0[2];
__IO uint32_t OUTENSET;
__IO uint32_t OUTENCLR;
__I uint32_t DUMMY1[2];
__IO uint32_t INTENSET;
__IO uint32_t INTENCLR;
__IO uint32_t INTTYPESET;
__IO uint32_t INTTYPECLR;
__IO uint32_t INTPOLSET;
__IO uint32_t INTPOLCLR;
__IO uint32_t INTSTATUS;
};
#define GPIO_GROUP0_REG_BASE 0x40001000
#define GPIO_GROUP1_REG_BASE 0x40002000
#define GPIO_GROUP0 ((struct LEGA_GPIO *)(GPIO_GROUP0_REG_BASE))
#define GPIO_GROUP1 ((struct LEGA_GPIO *)(GPIO_GROUP1_REG_BASE))
#if (defined LEGA_A0V1)
#define PAD_PE_REG 0x40000050
#define PAD_PS_REG 0x40000054
#else
#define PAD_PE_REG 0x40000014
#define PAD_PS_REG 0x40000018
#define PAD_IS_REG 0x4000001C
#define HW_CTRL_PE_PS 0x40000020
#endif
/*
LEGA GPIO END
*/
/*
LEGA I2C BEGIN
*/
typedef struct
{
__IO uint32_t IC_CON;
__IO uint32_t IC_TAR;
__IO uint32_t IC_SAR;
__IO uint32_t IC_HS_MADDR;
__IO uint32_t IC_DATA_CMD; //0x10
__IO uint32_t IC_SS_SCL_HCNT;
__IO uint32_t IC_SS_SCL_LCNT;
__IO uint32_t IC_FS_SCL_HCNT;
__IO uint32_t IC_FS_SCL_LCNT; //0x20
__IO uint32_t IC_HS_SCL_HCNT;
__IO uint32_t IC_HS_SCL_LCNT;
__IO uint32_t IC_INTR_STAT;
__IO uint32_t IC_INTR_MASK; //0x30
__IO uint32_t IC_RAW_INTR_STAT;
__IO uint32_t IC_RX_TL;
__IO uint32_t IC_TX_TL;
__IO uint32_t IC_CLR_INTR; //0x40
__IO uint32_t IC_CLR_UNDER;
__IO uint32_t IC_CLR_RX_OVER;
__IO uint32_t IC_CLR_TX_OVER;
__IO uint32_t IC_CLR_RD_REG; //0x50
__IO uint32_t IC_CLR_TX_ABRT;
__IO uint32_t IC_CLR_RX_DONE;
__IO uint32_t IC_CLR_ACTIVITY;
__IO uint32_t IC_CLR_STOP_DET; //0x60
__IO uint32_t IC_CLR_START_DET;
__IO uint32_t IC_CLR_GEN_CALL;
__IO uint32_t IC_ENABLE;
__IO uint32_t IC_STATUS; //0x70
__IO uint32_t IC_TXFLR;
__IO uint32_t IC_RXFLR;
__IO uint32_t IC_SDA_HOLD;
__IO uint32_t IC_TX_ABRT_SOURCE; //0x80
__IO uint32_t IC_SLV_DATA_NACK_ONLY;
__IO uint32_t IC_DMA_CR;
__IO uint32_t IC_DMA_TDLR;
__IO uint32_t IC_DMA_RDLR; //0x90
__IO uint32_t IC_SDA_SETUP;
__IO uint32_t IC_ACK_GENERAL_CALL;
__IO uint32_t IC_ENABLE_STATUS;
__IO uint32_t IC_FS_SPKLEN; //0xa0
__IO uint32_t IC_HS_SPKLEN;
__IO uint32_t IC_CLR_RESTART_DET;
__IO uint32_t IC_SCL_STUCK_AT_LOW_TIMEOUT;
__IO uint32_t IC_SDA_STUCK_AT_LOW_TIMEOUT; //0xb0
__IO uint32_t IC_CLR_SCL_STUCK_DET;
__IO uint32_t IC_DEVICE_ID;
__IO uint32_t IC_SMBUS_CLOCK_LOW_SEXT;
__IO uint32_t IC_SMBUS_CLOCK_LOW_MEXT; //0xc0
__IO uint32_t IC_SMBUS_THIGH_MAX_IDLE_COUNT;
__IO uint32_t IC_SMBUS_INTR_STAT;
__IO uint32_t IC_SMBUS_INTR_MASK;
__IO uint32_t IC_SMBUS_INTR_RAW_STATUS; //0xd0
__IO uint32_t IC_CLR_SMBUS_INTR;
__IO uint32_t IC_OPTIONAL_SAR;
__IO uint32_t IC_SMBUS_UDID_LSB;
__IO uint32_t RESERVED0; //0xe0
__IO uint32_t RESERVED1;
__IO uint32_t RESERVED2;
__IO uint32_t RESERVED3;
__IO uint32_t RESERVED4; //0xf0
__IO uint32_t IC_COMP_PARAM_1;
__IO uint32_t IC_COMP_VERSION;
__IO uint32_t IC_COMP_TYPE;
} I2C_TypeDef;
#define I2C0_BASE 0x4001A000
#define I2C1_BASE 0x4001B000
#define I2C0 ((I2C_TypeDef *)I2C0_BASE)
#define I2C1 ((I2C_TypeDef *)I2C1_BASE)
#define I2C0_SW_RESET_REG (SYS_REG_BASE + 0x938)
#define I2C1_SW_RESET_REG (SYS_REG_BASE + 0x93C)
// set pad2:3 for i2c0 func 4
#define I2C0_PINMUX_MASK0 0x0000FF00
#define I2C0_PINMUX_VALUE0 0x00004400
// set pad20:21 for i2c0 scl/sda func 1
#define I2C0_PINMUX_MASK1 0x00FF0000
#define I2C0_PINMUX_VALUE1 0x00110000
// set pad 8:9 for i2c1 func 3
#define I2C1_PINMUX_MASK0 0x000000FF
#define I2C1_PINMUX_VALUE0 0x00000033
// set pad22:23 for i2c1 scl/sda func 1
#define I2C1_PINMUX_MASK1 0xFF000000
#define I2C1_PINMUX_VALUE1 0x11000000
#define TX_EMPTY (1 << 4)
#define MST_ACTIVITY (1 << 5)
#define SLV_ACTIVITY (1 << 6)
#define RX_FULL (1 << 2)
#define RD_REQ (1 << 5)
#define TX_ABRT (1 << 6)
#define TFNF 0x02
#define M_STOP_DET (1 << 9)
#define M_ACTIVITY (1 << 8)
#define M_RX_DONE (1 << 7)
#define M_TX_ABRT (1 << 6)
#define M_RD_REQ (1 << 5)
#define M_TX_EMPTY (1 << 4)
#define M_TX_OVER (1 << 3)
#define M_RX_FULL (1 << 2)
#define M_RX_OVER (1 << 1)
#define M_RX_UNDER 1
#define IC_CON_RX_FIFO_FULL_HLD_CTRL (1 << 9) //IC_CON
#define IC_SLAVE_DISABLE (1 << 6)
#define IC_CON_IC_RESTART_EN (1 << 5) //IC_CON
#define IC_CON_IC_10BITADDR_MASTER (1 << 4)
#define IC_CON_IC_10BITADDR_SLAVE (1 << 3)
#define IC_CON_SS_MODE (1 << 1)
#define IC_CON_FS_MODE (2 << 1)
#define IC_CON_HS_MODE (3 << 1)
#define IC_CON_MASTER_MODE 1
#define IC_DATA_CMD_RESTART (1 << 10) //IC_DATA_CMD
#define IC_DATA_CMD_STOP (1 << 9)
#define IC_DATA_CMD_WRITE 0
#define IC_DATA_CMD_READ (1 << 8)
#define I2C_PAD_GROUP 0
#define MASTER_CODE 3 //default value is 1, can be 0 - 7
#define SS_SCL_HCNT 188 // +5+7
#define SS_SCL_LCNT 199 // +1
#define FS_SCL_HCNT 28//8 // +5+7
#define FS_SCL_LCNT 39//19 // +1
#define HS_SCL_HCNT 12 // +1+7
#define HS_SCL_LCNT 19 // +1
#define SAR_7BIT 0x54
#define SAR_10BIT 0x362
#if (defined LEGA_A0V1)
#define I2C0_CLK_CFG (SYS_REG_BASE + 0x840)
#define I2C1_CLK_CFG (SYS_REG_BASE + 0x844)
#define I2C1_CLK_EN (1)
#define I2C0_CLK_EN (1)
#elif (defined LEGA_A0V2)
#define I2C0_CLK_CFG (SYS_REG_BASE + 0x840)
#define I2C1_CLK_CFG (SYS_REG_BASE + 0x840)
#define I2C1_CLK_EN (1 << 1)
#define I2C0_CLK_EN (1)
#endif
/*
LEGA I2C END
*/
/*
LEGA PWM BEGIN
*/
struct LEGA_PWM
{
__IO uint32_t PWMCFG;
__IO uint32_t PWMINVERTTRIG;
__IO uint32_t PWM01TRIG;
__IO uint32_t PWM23TRIG;
__IO uint32_t PWM45TRIG;
__IO uint32_t PWMINTEN1;
__IO uint32_t PWMINTEN2;
__I uint32_t PWMRIS1;
__I uint32_t PWMRIS2;
__IO uint32_t PWMRIC1;
__IO uint32_t PWMRIC2;
__I uint32_t PWMIS1;
__I uint32_t PWMIS2;
__IO uint32_t PWMCTL;
__IO uint32_t PWM01LOAD;
__IO uint32_t PWM23LOAD;
__IO uint32_t PWM45LOAD;
__I uint32_t PWM01COUNT;
__I uint32_t PWM23COUNT;
__I uint32_t PWM45COUNT;
__IO uint32_t PWM0CMP;
__IO uint32_t PWM1CMP;
__IO uint32_t PWM2CMP;
__IO uint32_t PWM3CMP;
__IO uint32_t PWM4CMP;
__IO uint32_t PWM5CMP;
__IO uint32_t PWM01DB;
__IO uint32_t PWM23DB;
__IO uint32_t PWM45DB;
__IO uint32_t CAPCTL;
__IO uint32_t CAPINTEN;
__I uint32_t CAPRIS;
__IO uint32_t CAPIC;
__I uint32_t CAPIS;
__I uint32_t CAP01T;
__I uint32_t CAP23T;
__I uint32_t CAP45T;
__IO uint32_t CAP01MATCH;
__IO uint32_t CAP23MATCH;
__IO uint32_t CAP45MATCH;
__IO uint32_t TIMINTEN;
__I uint32_t TIMRIS;
__IO uint32_t TIMIC;
__I uint32_t TIMIS;
__IO uint32_t TIM01LOAD;
__IO uint32_t TIM23LOAD;
__IO uint32_t TIM45LOAD;
__IO uint32_t TIM01COUNT;
__IO uint32_t TIM23COUNT;
__IO uint32_t TIM45COUNT;
};
#define PWM_REG_BASE 0x40018000
#define PWM ((struct LEGA_PWM *)(PWM_REG_BASE))
#define PWM0_PINMUX_MASK 0x0F000000
#define PWM0_PINMUX_VALUE 0x01000000
#define PWM1_PINMUX_MASK 0x00000F00
#define PWM1_PINMUX_VALUE 0x00000100
#define PWM2_PINMUX_MASK 0xF0000000
#define PWM2_PINMUX_VALUE 0x10000000
#define PWM3_PINMUX_MASK 0x0000F000
#define PWM3_PINMUX_VALUE 0x00001000
#define PWM4_PINMUX_MASK 0x0F000000
#define PWM4_PINMUX_VALUE 0x04000000
#define PWM5_PINMUX_MASK 0x0000000F
#define PWM5_PINMUX_VALUE 0x00000004
#define PWM6_PINMUX_MASK 0xF0000000
#define PWM6_PINMUX_VALUE 0x40000000
#define PWM7_PINMUX_MASK 0x000000F0
#define PWM7_PINMUX_VALUE 0x00000040
#define COUNT_UP_MODE 0
#define COUNT_UP_DOWN_MODE 1
#define PWM_COUNT_MODE COUNT_UP_MODE
#define CNT_CLK_DIV_EN (0x00000001 << 27)
#define CNT_CLK_DIV_DIS 0
#define CLK_DIV_2 (0)
#define CLK_DIV_4 (0x00000001 << 24)
#define CLK_DIV_8 (0x00000002 << 24)
#define CLK_DIV_16 (0x00000003 << 24)
#define CLK_DIV_32 (0x00000004 << 24)
#define CLK_DIV_64 (0x00000005 << 24)
#define CLK_DIV_128 (0x00000006 << 24)
#define CLK_DIV_CFG CLK_DIV_8
#define PWM0_INVERT_EN (0x00000001 << 0)
#define PWM1_INVERT_EN (0x00000001 << 1)
#define PWM2_INVERT_EN (0x00000001 << 2)
#define PWM3_INVERT_EN (0x00000001 << 3)
#define PWM4_INVERT_EN (0x00000001 << 4)
#define PWM5_INVERT_EN (0x00000001 << 5)
#define PWM6_INVERT_EN (0x00000001 << 6)
#define PWM7_INVERT_EN (0x00000001 << 7)
#define PWMX_INVERT_EN 0
/*
LEGA PWM END
*/
/*
LEGA RTC BEGIN
*/
struct LEGA_RTC
{
__IO uint32_t CTRL;
__IO uint32_t CNT_TICK;
__IO uint32_t CNT_DATE;
__I uint32_t DUMMY[3];
__I uint32_t CURRENT_TICK;
__I uint32_t CURRENT_DATE;
};
#define RTC_REG_BASE 0x40000A20
#define RTC ((struct LEGA_RTC *)(RTC_REG_BASE))
#define RTC_CNT_CYCLE_ENABLE (1 << 15)
#define RTC_ENABLE (1 << 14)
#define CLK32K_SEL (1 << 12) //A0V1 bug, sel ext XO no function, same as internal RC clk
#define RTC_INT_ENABLE (1 << 11)
#define SW_OVERRIDE_REG_POR (1 << 4)
#define RTC_TICK_CNT 32768 //1s for asic
#define GET_RTC_CURRENT_DATE() (RTC->CURRENT_DATE)
#define RTC_INIT_YEAR 118 //2018
#define RTC_INIT_MONTH 8 //month 9
#define RTC_INIT_DATE 12
#define RTC_INIT_HOUR 8
#define RTC_INIT_MINUTE 0
#define RTC_INIT_SECOND 0
#define RTC_INIT_WEEKDAY 0 //auto modify
#define RTC_REFRESH_DAY 255 //255 max unit: day
#define RTC_REFRESH_HOUR 23 // 0 - 23
#define RTC_REFRESH_MINUTE 59 // 0 - 59
#define RTC_REFRESH_SECOND 59 // 0 - 59
#define RTC_MAX_DAY 256
#define SECOND_PER_DAY (24*3600)
#define LEGA_IRQ_STS_REG_ADDR 0x40000100
//retention ram addr need to be planned
#define RETENTION_RAM_ADDR 0x40008000
#define RTC_TIME_RETENTION_RAM_ADDR RETENTION_RAM_ADDR
#define POWERON_FLAG_RETENTION_RAM_ADDR (RETENTION_RAM_ADDR+0x10)
/*
LEGA RTC END
*/
/*
LEGA TIMER BEGIN
*/
struct LEGA_TIMER
{
__IO uint32_t LOAD;
__I uint32_t VALUE;
__IO uint32_t CONTROL;
__O uint32_t INTCLR;
__I uint32_t RIS;
__I uint32_t MIS;
__IO uint32_t BGLOAD;
};
#define TIMER1_REG_BASE 0x40017000
#define TIMER2_REG_BASE 0x40017020
#define TIMER1 ((struct LEGA_TIMER *)(TIMER1_REG_BASE))
#define TIMER2 ((struct LEGA_TIMER *)(TIMER2_REG_BASE))
#define COUNTER_16BIT 0
#define COUNTER_32BIT (1 << 1)
#define TIMER_SIZE COUNTER_32BIT
#define CLOCK_DIV_1 0
#define CLOCK_DIV_16 (1 << 2)
#define CLOCK_DIV_256 (2 << 2)
#define TIMER_PRESCALE CLOCK_DIV_1
#define FREE_RUNNING_MODE 0
#define PERIODIC_MODE (1 << 6)
#define ONE_SHOT_MODE 1
#define INTERRUPT_EN (1 << 5)
#define INTERRUPT_DIS 0
#define TIMER_ENABLE (1 << 7)
#define TIMER_DISABLE 0
/*
LEGA TIMER END
*/
/*
LEGA UART BEGIN
*/
typedef struct
{
union
{
__I uint8_t RBR;
__IO uint8_t THR;
__IO uint8_t DLL;
uint32_t RESERVED0; //0x0
};
union
{
__IO uint8_t DLH;
__IO uint32_t IER; //0x4
};
union
{
__I uint32_t IIR; //0x8
__IO uint8_t FCR;
};
__IO uint8_t LCR; //0xc
uint8_t RESERVED1[3];//Reserved
__IO uint32_t MCR; //0x10
__I uint8_t LSR; //0x14
uint8_t RESERVED2[3];//Reserved
__IO uint32_t MSR; //0x18
__IO uint8_t SCR; //0x1c
uint8_t RESERVED3[3];//Reserved
__IO uint32_t LPDLL; //0x20
__IO uint32_t LPDLH; //0x24
__IO uint32_t recerved[2];
union{
__IO uint32_t SRBR[16]; // 0x30~60xc
__IO uint32_t STHR[16];
};
__IO uint32_t FAR; //0x70
__IO uint32_t TFR; //0x7c
__IO uint32_t RFW;
__IO uint32_t USR;
__IO uint32_t TFL;
__IO uint32_t RFL;
__IO uint32_t SRR;
__IO uint32_t SRTS;
__IO uint32_t SBCR;
__IO uint32_t SDMAM;
__IO uint32_t SFE;
__IO uint32_t SRT;
__IO uint32_t STET; //0xa0
__IO uint32_t HTX;
__IO uint32_t DMASA; //0xa8
__IO uint32_t reserved[18];
__IO uint32_t CPR; //0xf4
__IO uint32_t UCV;
__IO uint32_t CTR;
}UART_TypeDef;
#define UART2 (UART_TypeDef*)0x40013000
#define UART1 (UART_TypeDef*)0x40012000
#define UART0 (UART_TypeDef*)0x40011000
/*UART*/
#define DW_UART_TX_TC (0x60)
/*UART_REST*/
#define DW_UART_SYS_RESET_LOW (0xA5)
#define DW_UART_SYS_RESET_HIGH (0x5A)
#define DW_UART_AHB_RESET_DIS (0x00<<1) // hclk
#define DW_UART_AHB_RESET_EN (0x01<<1) // hclk
#define DW_UART_FUN_RESET_DIS (0x00<<0) // sclk
#define DW_UART_FUN_RESET_EN (0x01<<0) // sclk
/* SRR */
#define DW_UART_SRR_UR (0x01)
#define DW_UART_SRR_RFR (0x02)
#define DW_UART_SRR_XFR (0x04)
#define DW_UART_LCR_DPS_MASK (0x3F)
#define DW_UART_LCR_DLAB (0x80)
/* USR */
#define DW_UART_USR_BUSY (0x01)
#define DW_UART_USR_TFNF (0x02)
#define DW_UART_USR_TFE (0x04)
#define DW_UART_USR_RFNE (0x08)
#define DW_UART_USR_RFF (0x10)
/* IER */
#define DW_UART_DISABLE_ALL_IRQ (0x00)
#define DW_UART_IER_RX_INT_EN (0x01)
#define DW_UART_IER_XMIT_EMPTY (0x02)
#define DW_UART_IER_LINE_STATUS (0x04)
#define DW_UART_IER_MDM_STATUS (0x08)
#define DW_UART_IER_PTIME (0x80)
/* LCR */
#define DW_UART_LCR_WORD_LEN_MASK (0x03)
#define DW_UART_LCR_STOP_BIT_MASK (0x04)
#define DW_UART_LCR_PARITY_MASK (0x38)
#define DW_UART_LCR_DPS_MASK (0x3F)
#define DW_UART_LCR_STICK_PARITY (0x20)
#define DW_UART_LCR_BREAK (0x40)
#define DW_UART_LCR_DLAB (0x80)
/* Word length values */
#define DW_UART_LCR_WORD_LEN5 (0x00)
#define DW_UART_LCR_WORD_LEN6 (0x01)
#define DW_UART_LCR_WORD_LEN7 (0x02)
#define DW_UART_LCR_WORD_LEN8 (0x03)
/* stop bit values */
#define DW_UART_LCR_1_STOP_BIT (0x00)
#define DW_UART_LCR_1D5_STOP_BIT (0x04)
#define DW_UART_LCR_2_STOP_BIT (0x04)
/* Parity bit values */
#define DW_UART_LCR_PARITY_NONE (0x00)
#define DW_UART_LCR_PARITY_ODD (0x08)
#define DW_UART_LCR_PARITY_EVEN (0x18)
#define DW_UART_LCR_PARITY_MARK (0x28)
#define DW_UART_LCR_PARITY_SPACE (0x38)
/* LSR */
#define DW_UART_LSR_DR (0x01)
#define DW_UART_LSR_OVERRUN (0x02)
#define DW_UART_LSR_PARITYERR (0x04)
#define DW_UART_LSR_FRAMEERR (0x08)
#define DW_UART_LSR_BREAKRCVD (0x10)
#define DW_UART_LSR_TX_THRE (0x20)
#define DW_UART_LSR_TX_TEMT (0x40)
#define DW_UART_LSR_RX_FIFOERR (0x80)
/* SFE */
#define DW_UART_SFE_SHADOW_FIFO_ENABLE (0x01)
/* SRT */
#define DW_UART_SRT_TRIGGER_LEVEL_1_CHAR (0x00)
#define DW_UART_SRT_TRIGGER_LEVEL_1_4_FULL (0x01)
#define DW_UART_SRT_TRIGGER_LEVEL_1_2_FULL (0x02)
#define DW_UART_SRT_TRIGGER_LEVEL_2_LESS_FULL (0x03)
/* STET*/
#define DW_UART_STET_FIFO_EMPTY (0x00)
#define DW_UART_STET_2_CHARS_IN_FIFO (0x01)
#define DW_UART_STET_1_4_FULL (0x02)
#define DW_UART_STET_1_2_FULL (0x03)
/* CPR*/
#define DW_UART_CPR_FIFO_STAT (1<<10)
#define DW_UART_CPR_FIFO_MODE_OFS (16)
#define DW_UART_CPR_FIFO_MODE_MASK (0xFF)
#define DW_UART_CPR_FIFO_MODE (0xFF0000)
/* FCR*/
#define DW_UART_FCR_FIFO_ENABLE (0x01)
#define DW_UART_FCR_FIFO_RCVR_RESET (0x02)
#define DW_UART_FCR_FIFO_XMIT_RESET (0x04)
#define DW_UART_FCR_FIFO_DMA_MODE (0x08)
/* TX EMPTY TRIGGER */
#define DW_UART_FCR_FIFO_TX_EMPTY (0x00)
#define DW_UART_FCR_FIFO_TX_TWO_CHAR (0x10)
#define DW_UART_FCR_FIFO_TX_QUATER_FULL (0x20)
#define DW_UART_FCR_FIFO_TX_HALF_FULL (0x30)
/* RCVR TRIGGER */
#define DW_UART_FCR_FIFO_RCVR_ONE_CHAR (0x00)
#define DW_UART_FCR_FIFO_RCVR_QUARTER_FULL (0x40)
#define DW_UART_FCR_FIFO_RCVR_HALF_FULL (0x80)
#define DW_UART_FCR_FIFO_RCVR_TWO_LESS (0xC0)
/*REGISTER ADDRESS*/
#define UART_CLK_REG_ADDR (0x40000820)
#define UART0_SCLK_EN (1 << 0)
#define UART1_SCLK_EN (1 << 1)
#define UART2_SCLK_EN (1 << 2)
#define UART_SCLK_ROOT_SEL_XTAL (1 << 3)
#define UART_SCLK_ROOT_SEL_APLL (0)
#define UART0_CLK_RST_REG_ADDR (0x40000920)
#define UART0_HCLK_RESET (1 << 1)
#define UART0_SCLK_RESET (1)
#define UART1_CLK_RST_REG_ADDR (0x40000924)
#define UART1_HCLK_RESET (1 << 1)
#define UART1_SCLK_RESET (1)
#define UART2_CLK_RST_REG_ADDR (0x40000928)
#define UART2_HCLK_RESET (1 << 1)
#define UART2_SCLK_RESET (1)
/*UART PINMUX*/
#if (defined LEGA_A0V1)
#define UART0_PIN_MUX_REG PINMUX_CTRL_REG0
#define UART1_PIN_MUX_REG PINMUX_CTRL_REG0
#define UART2_PIN_MUX_REG PINMUX_CTRL_REG0
#elif (defined LEGA_A0V2)
#define UART0_PIN_MUX_REG PINMUX_CTRL_REG0
#define UART1_PIN_MUX_REG PINMUX_CTRL_REG0
#define UART2_PIN_MUX_REG PINMUX_CTRL_REG1
#endif
#define DW_UART0_GPIO_MASK (0x000000FF) //GPIO0/1
#define DW_UART0_TX (0x00000001)
#define DW_UART0_RX (0x00000010)
#define DW_UART1_GPIO_MASK (0x0000FF00) //GPIO2/3
#define DW_UART1_TX (0x00000100)
#define DW_UART1_RX (0x00001000)
#define UART0_PAD_MASK (0x03)
#define UART1_PAD_MASK (0x0C)
#if (defined LEGA_A0V1)
#define DW_UART2_GPIO_MASK (0xFF000000) //GPIO6/7
#define DW_UART2_TX (0x03000000)
#define DW_UART2_RX (0x30000000)
#elif (defined LEGA_A0V2)
#define DW_UART2_GPIO_MASK (0x00FF0000) //GPIO12/13
#define DW_UART2_TX (0x00030000)
#define DW_UART2_RX (0x00300000)
#endif
//uart clock frequency setting
#ifdef LEGA_A0V1
#ifdef XTAL_40M
#define UART_BASE_CLOCK 20000000
#else
#define UART_BASE_CLOCK 13000000
#endif
#else //LEGA_A0V2
#define UART_BASE_CLOCK SYSTEM_CLOCK
#endif
extern uint8_t g_printf_uart;
#define uart_put_char(c) do{\
if(g_printf_uart == 0) \
{\
((UART0)->THR) = (c); \
while((((UART0)->LSR) & DW_UART_TX_TC) == 0);\
}\
else if(g_printf_uart == 1) \
{\
((UART1)->THR) = (c); \
while((((UART1)->LSR) & DW_UART_TX_TC) == 0);\
}\
else if(g_printf_uart == 2) \
{\
((UART2)->THR) = (c); \
while((((UART2)->LSR) & DW_UART_TX_TC) == 0);\
}\
}while(0)
/*
LEGA UART END
*/
/*
LEGA WDG BEGIN
*/
struct LEGA_WDOG
{
__IO uint32_t LOAD;
__I uint32_t VALUE;
__IO uint32_t CONTROL;
__O uint32_t INTCLR;
__I uint32_t RIS;
__I uint32_t MIS; //0x14
__I uint32_t DUMMY0[0x2FA];
__IO uint32_t LOCK; //0xC00
__I uint32_t DUMMY1[0xBF];
__IO uint32_t ITCR; //0xF00
__O uint32_t ITOP; //0xF04
__I uint32_t DUMMY2[0x32];
__I uint32_t PERIPHID4; //0xFD0
__I uint32_t PERIPHID5;
__I uint32_t PERIPHID6;
__I uint32_t PERIPHID7;
__I uint32_t PERIPHID0;
__I uint32_t PERIPHID1;
__I uint32_t PERIPHID2;
__I uint32_t PERIPHID3;
__I uint32_t PCELLID0;
__I uint32_t PCELLID1;
__I uint32_t PCELLID2;
__I uint32_t PCELLID3;
};
#define WDOG_BASE 0x40010000
#define WATCHDOG ((struct LEGA_WDOG *)(WDOG_BASE))
#define WDG_LOCK_TOKEN 0x1ACCE551
#define WDG_RESEN (1 << 1)
#define WDG_INTEN 1
/*
LEGA WDG END
*/
/*
LEGA EFUSE BEGIN
*/
struct LEGA_EFUSE
{
__IO uint32_t CFG_TYPE; //0x00
__IO uint32_t WR_TYPE;
__IO uint32_t START;
__IO uint32_t RD_CNT;
__IO uint32_t WR_CNT; //0x10
__IO uint32_t DIV_CNT;
__IO uint32_t B_ADDR;
__IO uint32_t PGM_DATA;
__IO uint32_t RDBK_DATA; //0x20
__I uint32_t RSVD;
__IO uint32_t INT_EN;
__IO uint32_t INT_CLR;
__IO uint32_t ENABLE; //0x30
};
#define EFUSE_CTRL_BASE 0x40005000
#define EFUSE ((struct LEGA_EFUSE *)(EFUSE_CTRL_BASE))
/*
LEGA EFUSE END
*/
#endif //_LEGA_PERIPHERAL_REG_H_

View file

@ -0,0 +1,73 @@
#ifndef _LEGA_PWM_H_
#define _LEGA_PWM_H_
#include <stdint.h>
#define PWM_OUTPUT_CH0 0
#define PWM_OUTPUT_CH1 1
#define PWM_OUTPUT_CH2 2
#define PWM_OUTPUT_CH3 3
#define PWM_OUTPUT_CH4 4
#define PWM_OUTPUT_CH5 5
#define PWM_OUTPUT_CH6 6
#define PWM_OUTPUT_CH7 7
#define LEGA_PWM_CH_NUM 8
typedef struct {
float duty_cycle; /* the pwm duty_cycle */
uint32_t freq; /* the pwm freq */
} lega_pwm_config_t;
typedef struct {
uint8_t port; /* pwm port */
lega_pwm_config_t config; /* spi config */
void *priv; /* priv data */
} lega_pwm_dev_t;
/**
* Initialises a PWM pin
*
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_init(lega_pwm_dev_t *pwm);
/**
* Starts Pulse-Width Modulation signal output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_start(lega_pwm_dev_t *pwm);
/**
* Stops output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_stop(lega_pwm_dev_t *pwm);
/**
* change the para of pwm
*
* @param[in] pwm the PWM device
* @param[in] para the para of pwm
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_para_chg(lega_pwm_dev_t *pwm, lega_pwm_config_t para);
/**
* De-initialises an PWM interface, Turns off an PWM hardware interface
*
* @param[in] pwm the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_finalize(lega_pwm_dev_t *pwm);
#endif //_LEGA_PWM_H_

View file

@ -0,0 +1,18 @@
#ifndef _LEGA_RND_H_
#define _LEGA_RND_H_
typedef struct {
char *p_workspace;
uint8_t *seed;
uint16_t seed_size;
uint8_t *rnd_data;
uint16_t rnd_size;
} lega_rnd_dev_t;
int lega_rnd_init(lega_rnd_dev_t *rnd);
int lega_rnd_generate(lega_rnd_dev_t *rnd);
int lega_rnd_finalize(lega_rnd_dev_t *rnd);
#endif //_LEGA_RND_H_

View file

@ -0,0 +1,70 @@
#ifndef _LEGA_RTC_H_
#define _LEGA_RTC_H_
#include <stdint.h>
#define HAL_RTC_FORMAT_DEC 1
#define HAL_RTC_FORMAT_BCD 2
typedef struct {
uint8_t format; /* time formart DEC or BCD */
} lega_rtc_config_t;
typedef struct {
uint8_t port; /* rtc port */
lega_rtc_config_t config; /* rtc config */
void *priv; /* priv data */
} lega_rtc_dev_t;
/*
* RTC time
*/
typedef struct {
uint8_t sec; /* DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
uint8_t min; /* DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
uint8_t hr; /* DEC format:value range from 0 to 23, BCD format:value range from 0x00 to 0x23 */
uint8_t weekday; /* DEC format:value range from 1 to 7, BCD format:value range from 0x01 to 0x07 */
uint8_t date; /* DEC format:value range from 1 to 31, BCD format:value range from 0x01 to 0x31 */
uint8_t month; /* DEC format:value range from 1 to 12, BCD format:value range from 0x01 to 0x12 */
uint8_t year; /* DEC format:value range from 0 to 99, BCD format:value range from 0x00 to 0x99 */
} lega_rtc_time_t;
/**
* This function will initialize the on board CPU real time clock
*
*
* @param[in] rtc rtc device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_init(lega_rtc_dev_t *rtc);
/**
* This function will return the value of time read from the on board CPU real time clock.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_get_time(lega_rtc_dev_t *rtc, lega_rtc_time_t *time);
/**
* This function will set MCU RTC time to a new value.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_set_time(lega_rtc_dev_t *rtc, const lega_rtc_time_t *time);
/**
* De-initialises an RTC interface, Turns off an RTC hardware interface
*
* @param[in] RTC the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_finalize(lega_rtc_dev_t *rtc);
#endif //_LEGA_RTC_H_

View file

@ -0,0 +1,294 @@
#ifndef _LEGA_SPI_H_
#define _LEGA_SPI_H_
#define SPI0 0x0
#define SPI1 0x1
#define SPI2 0x2
#define SPIx_BASE(i) (0x40014000 + ((i) * 0x1000))
#define SPIx_CTRL0(i) SPIx_BASE(i) + 0x0
#define SPI_DFS16_MASK 0xF
#define SPI_FR_SHIFT 4
#define SPI_FR_MOTOROLA 0x0
#define SPI_FR_TI 0x1
#define SPI_FR_NS 0x2
#define SPI_CPHA_SHIFT 6
#define SPI_CPHA 0x1
#define SPI_CPOL_SHIFT 7
#define SPI_CPOL 0x1
#define SPI_TMOD_SHIFT 8
#define SPI_TMOD_TR 0x0
#define SPI_TMOD_T 0x1
#define SPI_TMOD_R 0x2
#define SPI_TMODE_EEPROM 0x3
#define SPI_SLV_OE_SHIFT 10
#define SPI_SRL_SHIFT 11
#define SPI_CFS_SHIFT 12
#define SPI_DFS32_MASK 0xF
#define SPI_DFS32_SHIFT 16
#define SPI_FRF_SHIFT 21
#define SPI_FRF_STANDARD 0x0
#define SPI_FRF_DUAL 0x1
#define SPI_FRF_QUAD 0x2
//
#define SPIx_CTRL1(i) SPIx_BASE(i) + 0x4
#define SPI_NDF_MASK 0xFFFF
#define SPIx_SSIEN(i) SPIx_BASE(i) + 0x8
#define SPI_EN 0x1
#define SPI_DISABLE 0x0
#define SPIx_MWC(i) SPIx_BASE(i) + 0xc
#define SPI_MW_MOD (1 << 0)
#define SPI_MW_MDD (1 << 1)
#define SPI_MW_MHS (1 << 2)
#define SPIx_SE(i) SPIx_BASE(i) + 0x10
#define SPI_SLAVES_MASK 0xFFFF
//SPI_SLAVES_MASK dependend on hardware's setting
#define SPIx_BAUD(i) SPIx_BASE(i) + 0x14
#define SPI_BAUD_MASK 0xFFFF
#define SPIx_TXFTL(i) SPIx_BASE(i) + 0x18
#define SPI_TFT_MASK 0x7
//dependend on TX_ABW
#define SPIx_RXFTL(i) SPIx_BASE(i) + 0x1c
#define SPI_RFT_MASK 0x7
//dependend on RX_ABW
#define SPIx_TXFL(i) SPIx_BASE(i) + 0x20
#define SPI_TXFL_MASK 0x8
//dependend on TX_ABW
#define SPIx_RXFL(i) SPIx_BASE(i) + 0x24
#define SPI_RXFL_MASK 0x8
//dependend on RX_ABW
#define SPIx_ST(i) SPIx_BASE(i) + 0x28
#define SPI_ST_BUSY (1 << 0)
#define SPI_ST_TFNF (1 << 1)
#define SPI_ST_TFE (1 << 2)
#define SPI_ST_RFNE (1 << 3)
#define SPI_ST_RFF (1 << 4)
#define SPI_ST_TXE (1 << 5)
#define SPI_ST_DCOL (1 << 6)
#define SPIx_IM(i) SPIx_BASE(i) + 0x2c
#define SPIx_IS(i) SPIx_BASE(i) + 0x30
#define SPI_IS_TX_EMPTY (1 << 0)
#define SPI_IS_TX_OF (1 << 1)
#define SPI_IS_RX_UF (1 << 2)
#define SPI_IS_RX_OF (1 << 3)
#define SPI_IS_RX_FULL (1 << 4)
#define SPI_IS_MST (1 << 5)
#define SPI_IS_MSK (0x3F)
#define SPIx_RIS(i) SPIx_BASE(i) + 0x34
#define SPIx_TXOIC(i) SPIx_BASE(i) + 0x38
#define SPIx_RXOIC(i) SPIx_BASE(i) + 0x3c
#define SPIx_RXUIC(i) SPIx_BASE(i) + 0x40
#define SPIx_MSTIC(i) SPIx_BASE(i) + 0x44
#define SPIx_IC(i) SPIx_BASE(i) + 0x48
#define SPIx_DMAC(i) SPIx_BASE(i) + 0x4c
#define SPI_DMA_TX_EN (1 << 1)
#define SPI_DMA_RX_EN (1 << 0)
#define SPIx_DMATDL(i) SPIx_BASE(i) + 0x50
#define SPI_DMA_TDL_MASK 0x1F
//dependend on TX_ABW
#define SPIx_DMARDL(i) SPIx_BASE(i) + 0x54
#define SPI_DMA_RDL_MASK 0x1F
//dependend on RX_ABW
#define SPIx_ID(i) SPIx_BASE(i) + 0x58
#define SPIx_COMP_VER(i) SPIx_BASE(i) + 0x5c
#define SPIx_DR(i, j) SPIx_BASE(i) + 0x60 + (j) * 0x4
#define SPIx_RX_SAMPLE_DLY(i) SPIx_BASE(i) + 0xf0
#define SPIx_SPI_CTRL SPIx_BASE(i) + 0xf4
#define SPIx_RSVD1(i) SPIx_BASE(i) + 0xf8
#define SPIx_RSVD2(i) SPIx_BASE(i) + 0xfc
// DRAMC Registers
#define DMA_BASE 0x40004000
// ch0
#define DMA_SAR0_L *((volatile int *)(DMA_BASE+0x000))
#define DMA_SAR0_H *((volatile int *)(DMA_BASE+0x004))
#define DMA_DAR0_L *((volatile int *)(DMA_BASE+0x008))
#define DMA_DAR0_H *((volatile int *)(DMA_BASE+0x00C))
#define DMA_LLP0_L *((volatile int *)(DMA_BASE+0x010))
#define DMA_LLP0_H *((volatile int *)(DMA_BASE+0x014))
#define DMA_CTL0_L *((volatile int *)(DMA_BASE+0x018))
#define DMA_CTL0_H *((volatile int *)(DMA_BASE+0x01C))
#define DMA_SSTAT0_L *((volatile int *)(DMA_BASE+0x020))
#define DMA_SSTAT0_H *((volatile int *)(DMA_BASE+0x024))
#define DMA_DSTAT0_L *((volatile int *)(DMA_BASE+0x028))
#define DMA_DSTAT0_H *((volatile int *)(DMA_BASE+0x02C))
#define DMA_SSTATAR0_L *((volatile int *)(DMA_BASE+0x030))
#define DMA_SSTATAR0_H *((volatile int *)(DMA_BASE+0x034))
#define DMA_DSTATAR0_L *((volatile int *)(DMA_BASE+0x038))
#define DMA_DSTATAR0_H *((volatile int *)(DMA_BASE+0x03C))
#define DMA_CFG0_L *((volatile int *)(DMA_BASE+0x040))
#define DMA_CFG0_H *((volatile int *)(DMA_BASE+0x044))
#define DMA_SGR0_L *((volatile int *)(DMA_BASE+0x048))
#define DMA_SGR0_H *((volatile int *)(DMA_BASE+0x04C))
#define DMA_DSR0_L *((volatile int *)(DMA_BASE+0x050))
#define DMA_DSR0_H *((volatile int *)(DMA_BASE+0x054))
// ch1
#define DMA_SAR1_L *((volatile int *)(DMA_BASE+0x058))
#define DMA_SAR1_H *((volatile int *)(DMA_BASE+0x05C))
#define DMA_DAR1_L *((volatile int *)(DMA_BASE+0x060))
#define DMA_DAR1_H *((volatile int *)(DMA_BASE+0x064))
#define DMA_LLP1_L *((volatile int *)(DMA_BASE+0x068))
#define DMA_LLP1_H *((volatile int *)(DMA_BASE+0x06C))
#define DMA_CTL1_L *((volatile int *)(DMA_BASE+0x070))
#define DMA_CTL1_H *((volatile int *)(DMA_BASE+0x074))
#define DMA_SSTAT1_L *((volatile int *)(DMA_BASE+0x078))
#define DMA_SSTAT1_H *((volatile int *)(DMA_BASE+0x07C))
#define DMA_DSTAT1_L *((volatile int *)(DMA_BASE+0x080))
#define DMA_DSTAT1_H *((volatile int *)(DMA_BASE+0x084))
#define DMA_SSTATAR1_L *((volatile int *)(DMA_BASE+0x088))
#define DMA_SSTATAR1_H *((volatile int *)(DMA_BASE+0x08C))
#define DMA_DSTATAR1_L *((volatile int *)(DMA_BASE+0x090))
#define DMA_DSTATAR1_H *((volatile int *)(DMA_BASE+0x094))
#define DMA_CFG1_L *((volatile int *)(DMA_BASE+0x098))
#define DMA_CFG1_H *((volatile int *)(DMA_BASE+0x09C))
#define DMA_SGR1_L *((volatile int *)(DMA_BASE+0x0A0))
#define DMA_SGR1_H *((volatile int *)(DMA_BASE+0x0A4))
#define DMA_DSR1_L *((volatile int *)(DMA_BASE+0x0A8))
#define DMA_DSR1_H *((volatile int *)(DMA_BASE+0x0AC))
#define DMA_STATUSTFR *((volatile int *)(DMA_BASE+0x2e8))
#define DMA_STATUSBLOCK *((volatile int *)(DMA_BASE+0x2f0))
#define DMA_STATUSSRCTRAN *((volatile int *)(DMA_BASE+0x2f8))
#define DMA_STATUSDSTTRAN *((volatile int *)(DMA_BASE+0x300))
#define DMA_STATUSERR *((volatile int *)(DMA_BASE+0x308))
#define DMA_MASKTFR *((volatile int *)(DMA_BASE+0x310))
#define DMA_MASKBLOCK *((volatile int *)(DMA_BASE+0x318))
#define DMA_MASKSRCTRAN *((volatile int *)(DMA_BASE+0x320))
#define DMA_MASKDSTTRAN *((volatile int *)(DMA_BASE+0x328))
#define DMA_MASKERR *((volatile int *)(DMA_BASE+0x330))
#define DMA_CLEARTFR *((volatile int *)(DMA_BASE+0x338))
#define DMA_CLEARBLOCK *((volatile int *)(DMA_BASE+0x340))
#define DMA_CLEARSRCTRAN *((volatile int *)(DMA_BASE+0x348))
#define DMA_CLEARDSTTRAN *((volatile int *)(DMA_BASE+0x350))
#define DMA_CLEARERR *((volatile int *)(DMA_BASE+0x358))
#define DMACFGREG_L *((volatile int *)(DMA_BASE+0x398))
#define DMACFGREG_H *((volatile int *)(DMA_BASE+0x39C))
#define CHENREG_L *((volatile int *)(DMA_BASE+0x3A0))
#define CHENREG_H *((volatile int *)(DMA_BASE+0x3A4))
#define DMA_COMP_PARAMS_3_L *((volatile int *)(DMA_BASE+0x3E0))
#define DMA_COMP_PARAMS_3_H *((volatile int *)(DMA_BASE+0x3E4))
#define DMA_COMP_PARAMS_2_L *((volatile int *)(DMA_BASE+0x3E8))
#define DMA_COMP_PARAMS_2_H *((volatile int *)(DMA_BASE+0x3EC))
#define DMA_COMP_PARAMS_1_L *((volatile int *)(DMA_BASE+0x3F0))
#define DMA_COMP_PARAMS_1_H *((volatile int *)(DMA_BASE+0x3F4))
typedef struct spi_controller {
char *name;
volatile uint32_t left_tx_size;
volatile uint32_t left_rx_size;
void *pvtx;
void *pvrx;
void (*tx_func) (int port);
void (*rx_func) (int port);
uint8_t bits;
uint8_t lsb;
uint8_t is_loopback;
} lega_spi_controller_t;
typedef enum spi_trans_mode {
SPI_TRANS_PIO_MODE,
SPI_TRANS_DMA_MODE,
} lega_spi_trans_mode_t;
void tx_8bit(int port);
void rx_8bit(int port);
void tx_16bit(int port);
void rx_16bit(int port);
void tx_32bit(int port);
void rx_32bit(int port);
int spi_pio_trans_data(int port);
int spi_dma_trans_data(int port);
#define LEGA_SPI_MODE_MASTER 1 /* spi communication is master mode */
#define LEGA_SPI_MODE_SLAVE 2 /* spi communication is slave mode */
typedef struct {
uint32_t mode; /* spi communication mode */
uint32_t freq; /* communication frequency Hz */
} lega_spi_config_t;
typedef struct {
uint8_t port; /* spi port */
lega_spi_config_t config; /* spi config */
void *priv; /* priv data */
} lega_spi_dev_t;
/**
* Initialises the SPI interface for a given SPI device
*
* @param[in] spi the spi device
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_init(lega_spi_dev_t *spi);
/**
* Spi send
*
* @param[in] spi the spi device
* @param[in] data spi send data
* @param[in] size spi send data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_send(lega_spi_dev_t *spi, const uint8_t *data, uint16_t size, uint32_t timeout);
/**
* spi_recv
*
* @param[in] spi the spi device
* @param[out] data spi recv data
* @param[in] size spi recv data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_recv(lega_spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout);
/**
* spi send data and recv
*
* @param[in] spi the spi device
* @param[in] tx_data spi send data
* @param[in] rx_data spi recv data
* @param[in] size spi data to be sent and recived
* @param[in] timeout timeout in ms
*
* @return 0, on success; EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_send_recv(lega_spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data,
uint16_t size, uint32_t timeout);
/**
* De-initialises a SPI interface
*
*
* @param[in] spi the SPI device to be de-initialised
*
* @return 0 : on success, EIO : if an error occurred
*/
int32_t lega_spi_finalize(lega_spi_dev_t *spi);
#endif//_LEGA_SPI_H_

View file

@ -0,0 +1,67 @@
#ifndef _LEGA_TIMER_H_
#define _LEGA_TIMER_H_
#include <stdint.h>
#define LEGA_TIMER1_INDEX 0
#define LEGA_TIMER2_INDEX 1
#define LEGA_TIMER_NUM 2
#define TIMER_RELOAD_AUTO 1 /* timer reload automatic */
#define TIMER_RELOAD_MANU 2 /* timer reload manual */
typedef void (*lega_timer_cb_handler_t)(void *arg);
typedef struct {
lega_timer_cb_handler_t cb;
void *arg;
} lega_timer_cb_t;
typedef struct {
uint32_t period; /*us*/
uint8_t reload_mode;
lega_timer_cb_handler_t cb;
void *arg;
} lega_timer_config_t;
typedef struct {
int8_t port; /* timer port */
lega_timer_config_t config; /* timer config */
void *priv; /* priv data */
} lega_timer_dev_t;
/**
* init a hardware timer
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_timer_init(lega_timer_dev_t *tim);
/**
* start a hardware timer
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_timer_start(lega_timer_dev_t *tim);
/**
* stop a hardware timer
*
* @param[in] tim timer device
*
* @return none
*/
void lega_timer_stop(lega_timer_dev_t *tim);
/**
* De-initialises an TIMER interface, Turns off an TIMER hardware interface
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_timer_finalize(lega_timer_dev_t *tim);
#endif //_LEGA_TIMER_H_

View file

@ -0,0 +1,126 @@
#ifndef __LEGA_UART_H
#define __LEGA_UART_H
#include <stdint.h>
/* UART BAUDRATE*/
#define UART_BAUDRATE_110 (110)
#define UART_BAUDRATE_300 (300)
#define UART_BAUDRATE_600 (600)
#define UART_BAUDRATE_1200 (1200)
#define UART_BAUDRATE_2400 (2400)
#define UART_BAUDRATE_4800 (4800)
#define UART_BAUDRATE_9600 (9600)
#define UART_BAUDRATE_14400 (14400)
#define UART_BAUDRATE_19200 (19200)
#define UART_BAUDRATE_38400 (38400)
#define UART_BAUDRATE_57600 (57600)
#define UART_BAUDRATE_115200 (115200)
#define UART_BAUDRATE_230400 (230400)
#define UART_BAUDRATE_460800 (460800)
#define UART_BAUDRATE_921600 (921600)
#define UART_BAUDRATE_1000000 (1000000)
#define LEGA_UART0_INDEX 0
#define LEGA_UART1_INDEX 1
#define LEGA_UART2_INDEX 2
#define LEGA_UART_NUM 3
typedef void (*lega_uart_callback_func)(char);
/*
* UART data width
*/
typedef enum {
DATA_5BIT,
DATA_6BIT,
DATA_7BIT,
DATA_8BIT,
DATA_9BIT
} lega_uart_data_width_t;
/*
* UART stop bits
*/
typedef enum {
STOP_1BIT,
STOP_2BITS
} lega_uart_stop_bits_t;
/*
* UART flow control
*/
typedef enum {
FLOW_CTRL_DISABLED,
FLOW_CTRL_CTS,
FLOW_CTRL_RTS,
FLOW_CTRL_CTS_RTS
} lega_uart_flow_control_t;
/*
* UART parity
*/
typedef enum {
PARITY_NO,
PARITY_ODD,
PARITY_EVEN
} lega_uart_parity_t;
/*
* UART mode
*/
typedef enum {
TX_MODE,
RX_MODE,
TX_RX_MODE
} lega_uart_mode_t;
/*
* UART configuration
*/
typedef struct {
uint32_t baud_rate;
lega_uart_data_width_t data_width;
lega_uart_parity_t parity;
lega_uart_stop_bits_t stop_bits;
lega_uart_flow_control_t flow_control;
lega_uart_mode_t mode;
} lega_uart_config_t;
typedef struct {
uint8_t port; /* uart port */
lega_uart_config_t config; /* uart config */
void *priv; /* priv data */
} lega_uart_dev_t;
/**
* Initialises a UART interface
*
*
* @param[in] uart the interface which should be initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_init(lega_uart_dev_t *uart);
/**
* Transmit data on a UART interface
*
* @param[in] uart the UART interface
* @param[in] data pointer to the start of data
* @param[in] size number of bytes to transmit
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_send(lega_uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout);
/**
* Deinitialises a UART interface
*
* @param[in] uart the interface which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_finalize(lega_uart_dev_t *uart);
#endif //__LEGA_UART_H

View file

@ -0,0 +1,42 @@
#ifndef _LEGA_WDG_H_
#define _LEGA_WDG_H_
#include <stdint.h>
typedef struct {
uint32_t timeout; /* Watchdag timeout */
} lega_wdg_config_t;
typedef struct {
uint8_t port; /* wdg port */
lega_wdg_config_t config; /* wdg config */
void *priv; /* priv data */
} lega_wdg_dev_t;
#define WDG_TIMEOUT_MS (10000*(SYSTEM_CLOCK_NORMAL/SYSTEM_CLOCK)) // between 5s and 10s
/**
* This function will initialize the on board CPU hardware watch dog
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_wdg_init(lega_wdg_dev_t *wdg);
/**
* Reload watchdog counter.
*
* @param[in] wdg the watch dog device
*/
void lega_wdg_reload(lega_wdg_dev_t *wdg);
/**
* This function performs any platform-specific cleanup needed for hardware watch dog.
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_wdg_finalize(lega_wdg_dev_t *wdg);
#endif //_LEGA_WDG_H_

View file

@ -0,0 +1,11 @@
#ifndef __RF_SPI_H__
#define __RF_SPI_H__
#define RC_SW_CTRL_ADDR 0x60C0C004
#define SPI_COMMAND RC_SW_CTRL_ADDR
#define SPI_RDATA RC_SW_CTRL_ADDR
void spi_mst_write(uint16_t addr, uint16_t data );
uint16_t spi_mst_read(uint16_t addr);
#endif //__RF_SPI_H__

View file

@ -0,0 +1,186 @@
#include <stdint.h>
#include <math.h>
#include <stdio.h>
#include "lega_adc.h"
#include "lega_common.h"
#include "lega_gpio.h"
#if defined ADC_ENABLE
//void spi_mst_write(uint16_t addr, uint16_t data)
//{
// uint32_t pre = 8<<28;
// uint32_t start = 1 <<27;
// uint32_t readnotwrite = 0 <<26;
// uint32_t addr_t = addr <<16;
// uint32_t data_t = data << 0;
// uint32_t register_00 = pre | start | readnotwrite | addr_t | data_t ;
// uint32_t var=0;
// *((volatile int *) SPI_COMMAND)= register_00;
// do{
// var =(*((volatile int *)SPI_COMMAND)) & (0x1 << 27);
// }while(var);
//}
//uint16_t spi_mst_read(uint16_t addr)
//{
// uint32_t pre = 8 << 28;
// uint32_t start = 1 <<27;
// uint32_t readnotwrite = 1 <<26;
// uint32_t addr_t = addr <<16;
// uint32_t data_t = 0;
// uint32_t register_00 = pre | start | readnotwrite | addr_t | data_t ;
// uint32_t var=0;
// *((volatile uint32_t *) SPI_COMMAND) = register_00;
// do{
// var =( *((volatile uint32_t *) SPI_COMMAND) ) & (0x1 << 27);
// }while(var);
// return( (uint16_t)*((volatile uint32_t *) SPI_RDATA) );
//}
void adc_set_reg_bit(uint16_t reg, uint8_t start_bit, uint8_t len, uint16_t src_val)
{
uint16_t tmp,mask,val;
if((reg < 0xFF) && (start_bit < 16) && (len <= 16)&&(src_val<(1<<len)))
{
tmp = spi_mst_read(reg);
mask = (1<<len)-1; //1. clear dst bit. eg: len=4, mask = 0xf, 1111
mask = ~(mask<<start_bit); //~(mask<<4):0xff0f: 1111 1111 0000 1111
val = tmp & mask; //2.val =spi_read() & 0xff0f, clear [7:4]
src_val = (src_val << start_bit);
val = val | src_val; //3. val spi_read & 0xff0f | val << 4
spi_mst_write(reg,val);
}
else
{
return;
}
}
uint16_t adc_get_reg_bit(uint16_t reg, uint8_t start_bit, uint8_t len)
{
uint16_t mask,val;
if((reg < 0xFF) && (start_bit < 16) && (len <= 16))
{
val = spi_mst_read(reg); // 1. read reg val
mask = (1<<len)-1; //eg: len =4, 0xf,1111
mask = mask << start_bit; // 0x0f00;
val = val & mask; // 2. get dst bit
val = (val >> start_bit); // 3. ror
return val;
}
else
{
return -1;
}
}
/**
* founction for adc sample
* channnel pin which is set to adc sample.
* reference voltage 1.6V ADC resolution 12bit
* @param[in] channnel pin which is set to adc sample:rang0-7 (pad4-11)
*
* @return value:adc sample data rang:0-4095, -1: if channel invalid
*/
int32_t lega_adc_get(lega_adc_dev_t *adc_config)
{
uint16_t reg_f = 0;
uint32_t clk_reg[5] = {0};
uint32_t adc_base_reg[2] = {0};
int32_t vol_value = 0;
//float vol_val = 0;
lega_gpio_dev_t config_gpio;
if(adc_config->port > 7)
return -1;
config_gpio.port = adc_config->port+4;
config_gpio.config = LEGA_INPUT_HIGH_IMPEDANCE;
config_gpio.priv = NULL;
lega_gpio_init(&config_gpio);
//read clk reg value for restore
clk_reg[0] = REG_PL_RD(SYS_REG_BASE_WIFI_CLK);
clk_reg[1] = REG_PL_RD(SYS_REG_BASE_REF_ROOT_CLK);
clk_reg[2] = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR);
//Enable WiFi core clock
if(clk_reg[0] != 0x01)
{
REG_PL_WR(SYS_REG_BASE_WIFI_CLK,0x1);
delay(50);
}
//wifi ref clk sel to 52MHz
if(!(clk_reg[1] & 0x1))
{
REG_PL_WR(SYS_REG_BASE_REF_ROOT_CLK, REG_PL_RD(SYS_REG_BASE_REF_ROOT_CLK) | 0x1);
}
/* Enable RC clock */
if(!(clk_reg[2] & (uint32_t)0x08000000))
{
REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)1 << 27));
}
//read base reg
adc_base_reg[0] = REG_PL_RD(SYS_REG_BASE_AUXADC);
adc_base_reg[1] = REG_PL_RD(SYS_REG_BASE_XOCTRL2);
REG_PL_WR(SYS_REG_BASE_AUXADC, 0x040086CE);
REG_PL_WR(SYS_REG_BASE_AUXADC, REG_PL_RD(SYS_REG_BASE_AUXADC) & (~(uint32_t)(BIT(9))));
//Enable AUXADC
adc_set_reg_bit(0x06,14,1,0x0);
//Enable XO CLK AUCADC, DFF's RB;D_RST_XO_CLK_AUXADC= 0
reg_f = spi_mst_read(0x0f);
spi_mst_write(0x0f,0x8000);
//TRXTOP_LDO_BM, Tuning LDO output to 1.6V, default is 1.55V
adc_set_reg_bit(0x1E,3,3,0x7);
//Enable CLK AUXADC13M; D_XO_CLK_AUXADC13M_EN= 1
adc_set_reg_bit(0x75,14,1,0x1);
delay(500);
//Open selected channel
REG_PL_WR(SYS_REG_BASE_XOCTRL2, ((REG_PL_RD(SYS_REG_BASE_XOCTRL2)&(~(uint32_t)0x7))|(uint32_t)adc_config->port) | ((uint32_t)(BIT(9))));
//lega_rtos_delay_milliseconds(1);
delay(500);
REG_PL_WR(SYS_REG_BASE_AUXADC, REG_PL_RD(SYS_REG_BASE_AUXADC) | ((uint32_t)(BIT(9))));
vol_value = (spi_mst_read(0xA4) & 0xFFF0) >> 4;
printf("value is %ld\r\n",vol_value);
//vol_val = 1.6 * (float)vol_value/4095;
REG_PL_WR(SYS_REG_BASE_AUXADC,adc_base_reg[0]);
REG_PL_WR(SYS_REG_BASE_XOCTRL2,adc_base_reg[1]);
//Close AUXADC
adc_set_reg_bit(0x06,14,1,0x1);
//Close XO CLK AUCADC; D_RST_XO_CLK_AUXADC= 1
spi_mst_write(0x0f,reg_f);
//Close CLK AUXADC13M; D_XO_CLK_AUXADC13M_EN= 0
adc_set_reg_bit(0x75,14,1,0x0);
//restore clk reg
REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR,clk_reg[2]);
REG_PL_WR(SYS_REG_BASE_REF_ROOT_CLK,clk_reg[1]);
REG_PL_WR(SYS_REG_BASE_WIFI_CLK,clk_reg[0]);
return vol_value;
}
#endif

View file

@ -0,0 +1,55 @@
#include "lega_cm4.h"
#include "lega_flash.h"
/* Logic partition on flash devices */
const lega_logic_partition_t lega_partitions[] =
{
[PARTITION_BOOTLOADER] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "Bootloader",
.partition_start_addr = BOOTLOADER_FLASH_START_ADDR,
.partition_length = BOOTLOADER_MAX_SIZE, //64k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS,
},
[PARTITION_PARAMETER_1] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "Info",
.partition_start_addr = INFO_FLASH_START_ADDR,
.partition_length = INFO_MAX_SIZE, // 4k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
},
[PARTITION_PARAMETER_2] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "KV",
.partition_start_addr = KV_FLASH_START_ADDR,
.partition_length = KV_MAX_SIZE, //16k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
},
[PARTITION_PARAMETER_3] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "OLL", //offline log
.partition_start_addr = OLL_FLASH_START_ADDR,
.partition_length = OLL_MAX_SIZE, //16k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
},
[PARTITION_APPLICATION] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "Application",
.partition_start_addr = APP_FLASH_START_ADDR,
.partition_length = APP_MAX_SIZE, //984k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
},
[PARTITION_OTA_TEMP] =
{
.partition_owner = FLASH_EMBEDDED,
.partition_description = "OTA Storage",
.partition_start_addr = OTA_FLASH_START_ADDR,
.partition_length = OTA_MAX_SIZE, //656k bytes
.partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_EN,
}
};

View file

@ -0,0 +1,25 @@
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_boot.h"
uint8_t lega_get_boot_type(void)
{
uint32_t flag1 = REG_RD(POWERON_FLAG_RETENTION_RAM_ADDR);
uint32_t flag2 = REG_RD(AON_RST_CHECK_REG);
if((LEGA_AON_POWER_ON_FLAG == flag1) && (AON_RST_CHECK_FLAG == (flag2 & AON_RST_CHECK_FLAG)))
{
return SOFTWARE_RST;
}
else if((LEGA_AON_POWER_ON_FLAG == flag1) && (0 == flag2))
{
REG_WR(AON_RST_CHECK_REG, AON_RST_CHECK_FLAG);
return HARDWARE_PIN_RST;
}
else
{
REG_WR(AON_RST_CHECK_REG, AON_RST_CHECK_FLAG);
REG_WR(POWERON_FLAG_RETENTION_RAM_ADDR, LEGA_AON_POWER_ON_FLAG);
return PWR_ON_RST;
}
}

View file

@ -0,0 +1,365 @@
#include <stdbool.h>
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_dma.h"
#include "lega_spi.h"
//uint32_t peri_addr[8] = {0x40011000,0x40012000,0x40013000,0x40014000,0x40015000,0x40016000,0x4001A000,0x4001B000};
uint32_t peri_addr[8] = {(uint32_t)UART0,(uint32_t)UART1,(uint32_t)UART2,SPIx_BASE(SPI0),SPIx_BASE(SPI1),SPIx_BASE(SPI2),I2C0_BASE,I2C1_BASE};
uint8_t buff_p2m = 0;
lega_dma_callback_func g_lega_dma_callback_handler[LEGA_DMA_NUM];
void DMA_CTRL_IRQHandler(void)
{
uint8_t dma_ch = 0;
uint32_t dma_ctl_reg = 0;
if(REG_RD(DMA_STATUS_TFR_L_REG)&0x01)
{
dma_ch = 0;
dma_ctl_reg = DMA_CTL0_L_REG;
}
else
{
dma_ch = 1;
dma_ctl_reg = DMA_CTL1_L_REG;
}
if(lega_read32_bit(dma_ctl_reg,20,3) == P2M_MODE)
{
if(g_lega_dma_callback_handler[dma_ch])
{
g_lega_dma_callback_handler[dma_ch](buff_p2m);
}
}
if(dma_ch == 0)
{
if((CHENREG_L & 0x01)!=1)
CHENREG_L |= 0x0101;
}
else
{
if((CHENREG_L & 0x02)!=1)
CHENREG_L |= 0x0202;
}
//clear TFR int,channelx
REG_WR(DMA_CLEAR_TFR_L_REG,0x3);
//clear block int,channelx
REG_WR(DMA_CLEAR_BLOCK_L_REG,0x3);
}
/**
* Initialises a dma interface
*
*
* @param[in] dma the interface which should be initialised
*
* @return
*/
void lega_dma_init(lega_dma_dev_t *dma)
{
uint32_t handshake_src = 0;
uint32_t handshake_dest = 0;
uint32_t temp_val = 0;
lega_dma_config_reg_t config_reg = {0};
#ifdef LEGA_A0V2
lega_write32_bit(DMA_CLOCK_BASE,11,1,0x1);
#endif
if(dma->ch == 0)
{
config_reg.DMA_SAR_L = (uint32_t *)&DMA_SAR0_L;
config_reg.DMA_DAR_L = (uint32_t *)&DMA_DAR0_L;
config_reg.DMA_LLP_L = (uint32_t *)&DMA_LLP0_L;
config_reg.DMA_LLP_H = (uint32_t *)&DMA_LLP0_H;
config_reg.DMA_CTL_L_REG = DMA_CTL0_L_REG;
config_reg.DMA_CTL_H = (uint32_t *)&DMA_CTL0_H;
config_reg.DMA_CFG_L = (uint32_t *)&DMA_CFG0_L;
config_reg.DMA_CFG_H_REG = DMA_CFG0_H_REG;
}
else
{
config_reg.DMA_SAR_L = (uint32_t *)&DMA_SAR1_L;
config_reg.DMA_DAR_L = (uint32_t *)&DMA_DAR1_L;
config_reg.DMA_LLP_L = (uint32_t *)&DMA_LLP1_L;
config_reg.DMA_LLP_H = (uint32_t *)&DMA_LLP1_H;
config_reg.DMA_CTL_L_REG = DMA_CTL1_L_REG;
config_reg.DMA_CTL_H = (uint32_t *)&DMA_CTL1_H;
config_reg.DMA_CFG_L = (uint32_t *)&DMA_CFG1_L;
config_reg.DMA_CFG_H_REG = DMA_CFG1_H_REG;
}
// DMA_SAR1_L = (uint32_t)dma->src;
// DMA_DAR1_L = (uint32_t)dma->dest;
*((volatile int *)config_reg.DMA_SAR_L) = (uint32_t)dma->src;
*((volatile int *)config_reg.DMA_DAR_L) = (uint32_t)dma->dest;
//DMA LL
*((volatile int *)config_reg.DMA_LLP_L) = 0x00;
*((volatile int *)config_reg.DMA_LLP_H) = 0x00;
if(dma->mode == M2M_MODE)
{
//[26:25]=01, src AHB master 2
lega_write32_bit(config_reg.DMA_CTL_L_REG,25,2,0x1);
//[24:23]=00, dst AHB master 2
lega_write32_bit(config_reg.DMA_CTL_L_REG,23,2,0x1);
//[22:20]=001, mem-->mem, DW_ahb_dmac flow ctrl
lega_write32_bit(config_reg.DMA_CTL_L_REG,20,3,(uint32_t)dma->mode);
//[10:9]=0, src address increment
lega_write32_bit(config_reg.DMA_CTL_L_REG,9,2,0x0);
//[8:7]=10, dest address increment
lega_write32_bit(config_reg.DMA_CTL_L_REG,7,2,0x0);
handshake_src = 0;
handshake_dest = 0;
}
else if(dma->mode == M2P_MODE)
{
//[26:25]=01, src AHB master 2
lega_write32_bit(config_reg.DMA_CTL_L_REG,25,2,0x1);
//[24:23]=00, dst AHB master 1
lega_write32_bit(config_reg.DMA_CTL_L_REG,23,2,0x0);
//[22:20]=001, mem-->peri, DW_ahb_dmac flow ctrl
lega_write32_bit(config_reg.DMA_CTL_L_REG,20,3,(uint32_t)dma->mode);
//[10:9]=0, src address increment
lega_write32_bit(config_reg.DMA_CTL_L_REG,9,2,0x0);
//[8:7]=10, dest address no change
lega_write32_bit(config_reg.DMA_CTL_L_REG,7,2,0x2);
handshake_src = 0;
for(uint8_t i = 0;i < 8;i++)
{
if(dma->dest == peri_addr[i])
{
handshake_dest = 2*i;
break;
}
}
}
else if(dma->mode == P2M_MODE)
{
//[26:25]=01, src AHB master 1
lega_write32_bit(config_reg.DMA_CTL_L_REG,25,2,0x0);
//[24:23]=00, dst AHB master 2
lega_write32_bit(config_reg.DMA_CTL_L_REG,23,2,0x1);
//[22:20]=001, peri-->mem, DW_ahb_dmac flow ctrl
lega_write32_bit(config_reg.DMA_CTL_L_REG,20,3,(uint32_t)dma->mode);
//[10:9]=0, src address no change
lega_write32_bit(config_reg.DMA_CTL_L_REG,9,2,0x2);
//[8:7]=10, dest address no change
lega_write32_bit(config_reg.DMA_CTL_L_REG,7,2,0x2);
handshake_dest = 0;
for(uint8_t i = 0;i < 8;i++)
{
if(dma->src == peri_addr[i])
{
handshake_src = 2*i+1;
break;
}
}
*((volatile int *)config_reg.DMA_CTL_H) = 1;
*((volatile int *)config_reg.DMA_DAR_L) = (uint32_t)&buff_p2m;
}
else if(dma->mode == P2P_MODE)
{
//[26:25]=01, src AHB master 1
lega_write32_bit(config_reg.DMA_CTL_L_REG,25,2,0x0);
//[24:23]=00, dst AHB master 1
lega_write32_bit(config_reg.DMA_CTL_L_REG,23,2,0x0);
//[22:20]=001, peri-->peri, DW_ahb_dmac flow ctrl
lega_write32_bit(config_reg.DMA_CTL_L_REG,20,3,(uint32_t)dma->mode);
//[10:9]=0, src address no change
lega_write32_bit(config_reg.DMA_CTL_L_REG,9,2,0x2);
//[8:7]=10, dest address no change
lega_write32_bit(config_reg.DMA_CTL_L_REG,7,2,0x2);
for(uint8_t i = 0;i < 8;i++)
{
if(dma->src == peri_addr[i])
{
handshake_src = 2*i+1;
break;
}
}
for(uint8_t i = 0;i < 8;i++)
{
if(dma->dest == peri_addr[i])
{
handshake_dest = 2*i;
break;
}
}
*((volatile int *)config_reg.DMA_CTL_H) = 1;
}
//[16:14]=000, src_size=1
lega_write32_bit(config_reg.DMA_CTL_L_REG,14,3,0x0);
//[13:11]=001, dest_size=1
lega_write32_bit(config_reg.DMA_CTL_L_REG,11,3,0x0);
//[6:4]=010, source width=8bit
lega_write32_bit(config_reg.DMA_CTL_L_REG,4,3,0x0);
//[3:1]=000, destination width=8bit
lega_write32_bit(config_reg.DMA_CTL_L_REG,1,3,0x0);
//[0]=1, int enable
lega_write32_bit(config_reg.DMA_CTL_L_REG,0,1,0x1);
//DMA channelx CFG,config handshake signal with peri chip
//[31], reload DST, [19:18], interface polarity active high, [11]=1 src software,[10]=0 dest hardware
*((volatile int *)config_reg.DMA_CFG_L) = 0x00000000;
//[14:11]=2,dest chx
lega_write32_bit(config_reg.DMA_CFG_H_REG,11,4,handshake_dest);
//[10:7]=2,src chx
lega_write32_bit(config_reg.DMA_CFG_H_REG,7,4,handshake_src);
//enable fifo mode
lega_write32_bit(config_reg.DMA_CFG_H_REG,1,1,0x1);
if((dma->mode == P2M_MODE) || (dma->mode == P2P_MODE))
{
//enable dma int
NVIC_EnableIRQ(DMA_CTRL_IRQn);
if(dma->ch == 0)
{
//unmask TFR int
temp_val = REG_RD(DMA_MASK_TFR_L_REG);
REG_WR(DMA_MASK_TFR_L_REG,temp_val | 0X0101);
//unmask BLOCK int
temp_val = REG_RD(DMA_MASK_BLOCK_L_REG);
REG_WR(DMA_MASK_BLOCK_L_REG,temp_val | 0X0101);
}
else
{
//unmask TFR int
temp_val = REG_RD(DMA_MASK_TFR_L_REG);
REG_WR(DMA_MASK_TFR_L_REG,temp_val | 0X0202);
//unmask BLOCK int
temp_val = REG_RD(DMA_MASK_BLOCK_L_REG);
REG_WR(DMA_MASK_BLOCK_L_REG,temp_val | 0X0202);
}
}
//enable dma
DMACFGREG_L = 0x1;
if((dma->mode == P2M_MODE)||(dma->mode == P2P_MODE))
{
//enable channel X
if(dma->ch == 0)
{
CHENREG_L = 0x0101;
}
else
{
CHENREG_L = 0x0202;
}
}
if(dma->priv)
{
g_lega_dma_callback_handler[dma->ch] = (lega_dma_callback_func)(dma->priv);
}
}
/**
* Transmit data on a dma interface
*
* @param[in] dma the dma interface
* @param[in] size number of bytes to transmit
*
* @return
*/
void lega_dma_send(lega_dma_dev_t *dma,/*const void *data,*/ uint32_t size, uint32_t timeout)
{
if(dma->ch == 0)
{
//if(CHENREG_L & 0x01)
//{
// lega_write32_bit(DMA_CFG0_L_REG,8,1,0x01);
// while(lega_read32_bit(DMA_CFG0_L_REG,9,1) == 0);
// CHENREG_L = 0X0100;
//}
while(CHENREG_L&0x01);
DMA_SAR0_L = (uint32_t)dma->src;
DMA_DAR0_L = (uint32_t)dma->dest;
DMA_CTL0_H = size;
//enable dma
//DMACFGREG_L = 0x1;
//enable channel 0
//while(CHENREG_L&0x01);
CHENREG_L = 0x0101;
}
else
{
//if(CHENREG_L & 0x02)
//{
// lega_write32_bit(DMA_CFG1_L_REG,8,1,0x01);
// while(lega_read32_bit(DMA_CFG1_L_REG,9,1) == 0);
// CHENREG_L = 0X0200;
//}
while(CHENREG_L&0x02);
DMA_SAR1_L = (uint32_t)dma->src;
DMA_DAR1_L = (uint32_t)dma->dest;
DMA_CTL1_H = size;
//enable dma
//DMACFGREG_L = 0x1;
//enable channel 1
//while(CHENREG_L&0x02);
CHENREG_L = 0x0202;
}
}
/**
* Deinitialises a dma interface
*
* @param[in] DMA the interface which should be deinitialised
*
* @return
*/
void lega_dma_finalize(lega_dma_dev_t *dma)
{
uint32_t temp_val = 0;
if(dma->ch == 0)
{
//unmask TFR int
temp_val = REG_RD(DMA_MASK_TFR_L_REG);
REG_WR(DMA_MASK_TFR_L_REG,temp_val & (~(0X0001)));
//unmask BLOCK int
temp_val = REG_RD(DMA_MASK_BLOCK_L_REG);
REG_WR(DMA_MASK_BLOCK_L_REG,temp_val & (~(0X0001)));
if(CHENREG_L & 0x01)
{
lega_write32_bit(DMA_CFG0_L_REG,8,1,0x01);
while(lega_read32_bit(DMA_CFG0_L_REG,9,1) == 0);
CHENREG_L = 0X0100;
}
DMA_SAR0_L = 0;
DMA_DAR0_L = 0;
}
else
{
//unmask TFR int
temp_val = REG_RD(DMA_MASK_TFR_L_REG);
REG_WR(DMA_MASK_TFR_L_REG,temp_val & (~(0X0002)));
//unmask BLOCK int
temp_val = REG_RD(DMA_MASK_BLOCK_L_REG);
REG_WR(DMA_MASK_BLOCK_L_REG,temp_val & (~(0X0002)));
if(CHENREG_L & 0x02)
{
lega_write32_bit(DMA_CFG1_L_REG,8,1,0x01);
while(lega_read32_bit(DMA_CFG1_L_REG,9,1) == 0);
CHENREG_L = 0X0200;
}
DMA_SAR1_L = 0;
DMA_DAR1_L = 0;
}
g_lega_dma_callback_handler[dma->ch] = NULL;
//close dma
if((DMA_SAR0_L == 0)&&(DMA_SAR1_L == 0))
{
NVIC_DisableIRQ(DMA_CTRL_IRQn);
//disable dma
DMACFGREG_L = 0x0;
//close dma clock
//lega_write32_bit(DMA_CLOCK_BASE,11,1,0x1);
}
}

View file

@ -0,0 +1,132 @@
#include <string.h>
#include <stdlib.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_efuse.h"
#include "rf_spi.h"
void efuse_ldo25_open(void)
{
uint16_t tmp_16;
uint32_t tmp_32;
// ----- Change APLL clock to 80MHz -----
SYS_CRM_WIFI_BLK_CLK = 0x1; // Enable WiFi core clock
delay(5); // wait for a few cycles for WiFi core clock settle
MDM_CLKGATEFCTRL0 = (0x1<<27); // Force RC clock open
//open 10uA current
tmp_16 = spi_mst_read(TRX_PD_CTRL1_REG_ADDR);
tmp_16 &= (~(0x0001 << 13)); //clear bit13 (D_PD_BG)
spi_mst_write(TRX_PD_CTRL1_REG_ADDR, tmp_16);
tmp_16 = spi_mst_read(TRX_PD_CTRL2_REG_ADDR);
tmp_16 &= (~(0x0003 << 2)); //clear bit<3:2> (D_PD_TRXTOP_BIAS, D_PD_TRXTOP_LDO)
spi_mst_write(TRX_PD_CTRL2_REG_ADDR, tmp_16);
//open PU LDO25: set D_AON_RCO32K_REG1<13> to 1
tmp_32 = RTC_REG_RCO32K;
RTC_REG_RCO32K = tmp_32 | (0x00000001 << (13 + 16));
//adjust PU LDO25 voltage: set D_AON_RCO32K_REG1<12:9> to 4'b0011
tmp_32 = RTC_REG_RCO32K;
tmp_32 &= ~(0x0000000F << (9 + 16));
tmp_32 |= (0x00000003 << (9 + 16));
RTC_REG_RCO32K = tmp_32;
}
/*
efuse init, must be called before read/write operation
if efuse write is needed, ldo25_open must be set to 1
if only efuse read is needed, then ldo25_open should be set to 0
*/
void lega_efuse_init(uint8_t ldo25_open)
{
EFUSE->RD_CNT = EFUSE_READ_OP_WAIT_CYCLE;
EFUSE->WR_CNT = EFUSE_WRITE_OP_WAIT_CYCLE;
EFUSE->DIV_CNT = EFUSE_DIV_OP_WAIT_CYCLE;
if(ldo25_open)
{
efuse_ldo25_open();
}
}
/*
read one efuse byte
param-addr: efuse addr, from 0x000 to 0x1FF
*/
uint8_t lega_efuse_byte_read(uint16_t addr)
{
EFUSE->B_ADDR = addr;
EFUSE->CFG_TYPE = 0x0;//read type
EFUSE->START = 0x1;
while(EFUSE->START & 0x1);
return EFUSE->RDBK_DATA;
}
/*
read one efuse word
param-addr: efuse addr, from 0x000 to 0x1FC
*/
uint32_t lega_efuse_word_read(uint16_t addr)
{
uint32_t rd_word_data = 0;
uint8_t rd_byte_data = 0;
for(int i = 0; i < 4; i++)
{
rd_byte_data = lega_efuse_byte_read(addr+i);
rd_word_data |= rd_byte_data << (i<<3);
}
return rd_word_data;
}
/*
program one efuse byte
param-addr: efuse addr, from 0x000 to 0x1FF
param-data: data to be written
*/
void lega_efuse_byte_write(uint16_t addr, uint8_t data)
{
EFUSE->PGM_DATA = data;
EFUSE->B_ADDR = addr;
EFUSE->CFG_TYPE = 0x1;//program type
EFUSE->WR_TYPE = 0x0;//write type: byte
EFUSE->START = 0x1;
while(EFUSE->START & 0x1);
}
/*
program one efuse word
param-addr: efuse addr, from 0x000 to 0x1FC
param-data: data to be written
*/
void lega_efuse_word_write(uint16_t addr, uint32_t data)
{
EFUSE->PGM_DATA = data;
EFUSE->B_ADDR = addr;
EFUSE->CFG_TYPE = 0x1;//program type
EFUSE->WR_TYPE = 0x1;//write type: word
EFUSE->START = 0x1;
while(EFUSE->START & 0x1);
}
/*
read multiple efuse bytes
param-start_addr: efuse addr, from 0x000 to 0x1FF
param-size_in_bytes: how many bytes to be read
param-pData: where efuse data is stored
*/
void lega_efuse_multi_read(uint16_t start_addr, uint16_t size_in_bytes, uint8_t *pData)
{
uint16_t i;
//efuse init
lega_efuse_init(EFUSE_LDO25_CLOSE);
//efuse byte read
for(i = 0; i < size_in_bytes; i++)
{
*(pData+i) = lega_efuse_byte_read(start_addr+i);
}
}

View file

@ -0,0 +1,235 @@
#include <stdio.h>
#include <string.h>
#include "lega_cm4.h"
#include "lega_flash_alg.h"
#include "lega_flash.h"
extern const lega_logic_partition_t lega_partitions[];
#define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1))
/**
* lega flash init
*
* @note this function must be called before flash erase/write operation
* also, this function must not be interrupted, it should be called
* with interrupt disabled
* @param[in] none
*
* @return HAL_logi_partition struct
*/
int32_t lega_flash_init(void)
{
return lega_flash_alg_init();
}
/**
* Get the infomation of the specified flash area
*
* @param[in] in_partition The target flash logical partition
*
* @return HAL_logi_partition struct
*/
lega_logic_partition_t *lega_flash_get_info(lega_partition_t in_partition)
{
lega_logic_partition_t *logic_partition;
logic_partition = (lega_logic_partition_t *)&lega_partitions[ in_partition ];
return logic_partition;
}
/**
* Erase an area on a Flash logical partition
*
* @note Erase on an address will erase all data on a sector that the
* address is belonged to, this function does not save data that
* beyond the address area but in the affected sector, the data
* will be lost.
* this function must not be interrupted, it should be called with
* interrupt disabled
*
* @param[in] in_partition The target flash logical partition which should be erased
* @param[in] off_set Start address of the erased flash area
* @param[in] size Size of the erased flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_erase(lega_partition_t in_partition, uint32_t off_set, uint32_t size)
{
uint32_t addr;
uint32_t start_addr, end_addr;
int32_t ret = 0;
lega_logic_partition_t *partition_info;
partition_info = lega_flash_get_info( in_partition );
if(size + off_set > partition_info->partition_length)
{
return -1;
}
start_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set), SPI_FLASH_SEC_SIZE);
end_addr = ROUND_DOWN((partition_info->partition_start_addr + off_set + size - 1), SPI_FLASH_SEC_SIZE);
for (addr = start_addr; addr <= end_addr; addr += SPI_FLASH_SEC_SIZE)
{
ret = lega_flash_alg_erase(SECTOR_ERASE_CMD, addr);
if (ret != 0)
{
return ret;
}
}
return 0;
}
/**
* Write data to an area on a flash logical partition without erase
*
* @note this function must not be interrupted, it should be called with
* interrupt disabled
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_write(lega_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len)
{
uint32_t start_addr, end_addr;
lega_logic_partition_t *partition_info;
uint8_t *p_buf = (uint8_t *)(in_buf);
uint32_t prg_size;
uint32_t left_buf_len = in_buf_len;
partition_info = lega_flash_get_info( in_partition );
if(off_set == NULL || in_buf == NULL || ((*off_set + in_buf_len) > partition_info->partition_length))
{
// ptr and size over range check
return -1;
}
start_addr = partition_info->partition_start_addr + *off_set;
end_addr = start_addr + left_buf_len;
while(left_buf_len > 0)
{
if((end_addr / SPI_FLASH_PAGE_SIZE) > (start_addr / SPI_FLASH_PAGE_SIZE))
{
prg_size = SPI_FLASH_PAGE_SIZE - (start_addr % SPI_FLASH_PAGE_SIZE);
}
else
{
prg_size = left_buf_len;
}
lega_flash_alg_programpage(start_addr, prg_size, p_buf);
p_buf += prg_size;
start_addr += prg_size;
left_buf_len -= prg_size;
}
*off_set += in_buf_len;
return 0;
}
/**
* Write data to an area on a flash logical partition with erase first
*
* @note this function must not be interrupted, it should be called with
* interrupt disabled
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_erase_write(lega_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len)
{
int32_t ret = 0;
ret = lega_flash_erase(in_partition, *off_set, in_buf_len);
if (ret != 0)
{
return ret;
}
return lega_flash_write(in_partition, off_set, in_buf, in_buf_len);
}
/**
* Read data from an area on a Flash to data buffer in RAM
*
* @param[in] in_partition The target flash logical partition which should be read
* @param[in] off_set Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] outBuffer Point to the data buffer that stores the data read from flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_read(lega_partition_t in_partition, uint32_t *off_set,
void *out_buf, uint32_t in_buf_len)
{
int32_t ret = 0;
uint32_t start_addr;
lega_logic_partition_t *partition_info;
partition_info = lega_flash_get_info( in_partition );
if(off_set == NULL || out_buf == NULL || *off_set + in_buf_len > partition_info->partition_length)
{
return -1;
}
start_addr = partition_info->partition_start_addr + *off_set;
memcpy(out_buf, (void *)(start_addr), in_buf_len);
*off_set += in_buf_len;
return ret;
}
/**
* Set security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of enabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_enable_secure(lega_partition_t partition, uint32_t off_set, uint32_t size)
{
return 0;
}
/**
* Disable security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of disabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t lega_flash_dis_secure(lega_partition_t partition, uint32_t off_set, uint32_t size)
{
return 0;
}

View file

@ -0,0 +1,705 @@
/***********************************************************************/
/* This file is part of the ARM Toolchain package */
/* Copyright (c) 2010 Keil - An ARM Company. All rights reserved. */
/***********************************************************************/
/* */
/* FlashDev.C: Flash Programming Functions adapted */
/* for New Device 256kB Flash */
/* */
/***********************************************************************/
#include <stdlib.h>
#include "lega_flash_alg.h" // FlashOS Structures
#include "lega_cm4.h"
#include "lega_common.h"
FLASH_DRIVER_SEG void lega_flash_alg_cache_bypass(void)
{
//cache bypass
if(!(FLASH_CACHE_CTRL & CACHE_BYPASS))
{
FLASH_CACHE_CTRL = CACHE_BYPASS;
}
}
FLASH_DRIVER_SEG void lega_flash_alg_cache_enable(void)
{
//cache enable
if(FLASH_CACHE_CTRL & CACHE_BYPASS)
{
//cache flush, set bit0
FLASH_CACHE_CTRL = CACHE_BYPASS | CACHE_FLUSH;
//disable cache bypass
FLASH_CACHE_CTRL = 0x00;
}
}
FLASH_DRIVER_SEG void lega_flash_alg_cache_flush(void)
{
if(FLASH_CACHE_CTRL & CACHE_BYPASS) //if cache already bypass, do nothing
{
return;
}
//enable cache bypass
FLASH_CACHE_CTRL = CACHE_BYPASS;
//set bit0
FLASH_CACHE_CTRL = CACHE_BYPASS | CACHE_FLUSH;
//disable cache bypass
FLASH_CACHE_CTRL = 0x00;
}
FLASH_DRIVER_SEG void lega_flash_alg_f_delay(unsigned char cycle)
{
while(cycle--)
__asm("nop");
}
#if (defined LEGA_A0V1)
FLASH_DRIVER_SEG int lega_flash_alg_init(void)
{
int var_rdata = 0;
int cmp_rdata = 0;
while((FLASH->BUSY & 0x01) ==1);
FLASH->CMD = RDID; //WRITE
FLASH->LENGTH = 0;
FLASH->ADDR = 0;
FLASH->DUMMY = 0;
FLASH->SBUS_START = 0x01; //WRITE
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01) ==1);
var_rdata = FLASH->ID; //READ
cmp_rdata = var_rdata>>16;
if(cmp_rdata == 0xC2) {
FLASH->CFG = 0x110;
}
else if((cmp_rdata == 0xEF)||(cmp_rdata == 0x0B)) {
FLASH->CFG = 0x210;
}
else if(cmp_rdata == 0xC8) {
FLASH->CFG = 0x410;
}
FLASH->IBUS_CMD = 0x3B; //2-wire
return (0); // Finished without Errors
}
/*
* Erase complete Flash Memory
* Return Value: 0 - OK, 1 - Failed
*/
FLASH_DRIVER_SEG int lega_flash_alg_erasechip (void) {
volatile int var_rdata = 0;
volatile int cycle_count = 0;
while((FLASH->BUSY & 0x01)==1);
//configure XTX mode, disable auto ERA nor PRG
FLASH->CFG = 0x200;
do
{ //write enable
FLASH->CMD = WREN;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read Device status register
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
var_rdata = FLASH->STATUS;//READ status
cycle_count++;
if(cycle_count == 5)
{
return 1;
}
}while(((var_rdata>>1) & 0x01 )==0);
cycle_count = 0;
//set command CE
FLASH->CMD = CE;
FLASH->LENGTH = 0;
FLASH->DUMMY = 0;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
//check busy
while((FLASH->BUSY & 0x01)==1);
do
{ //set command Read Device status reg
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read flash controller status register
var_rdata = FLASH->STATUS;
cycle_count++;
//cycle_count value caculated by operation(chip erase) under related Flash clock.
//time value here used for timeout check is enough
if(cycle_count == 200000000)
{
return 1;
}
}while((var_rdata & 0x01)==1);
cycle_count = 0;
return (0); // Finished without Errors
}
/*
* Erase Sector in Flash Memory
* Parameter: adr: Sector Address
* Return Value: 0 - OK, 1 - Failed
*/
FLASH_DRIVER_SEG int lega_flash_alg_erasesector(unsigned long adr)
{
volatile int var_rdata = 0;
volatile int cycle_count = 0;
/* Add your Code */
while((FLASH->BUSY & 0x01)==1);
do
{ //write enable
FLASH->CMD = WREN;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read Device status register
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
var_rdata = FLASH->STATUS;//READ status
cycle_count++;
if(cycle_count == 5)
{
return adr;
}
}while(((var_rdata>>1) & 0x01 )==0);
cycle_count = 0;
//set command SE
FLASH->CMD = SE;
FLASH->ADDR = adr;
FLASH->LENGTH = 0;
FLASH->DUMMY = 0;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
//check busy
while((FLASH->BUSY & 0x01)==1);
do
{ //set command Read Device status reg
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read flash controller status register
var_rdata = FLASH->STATUS;
cycle_count++;
//time out check
if(cycle_count == 5000000)
{
return adr;
}
}while((var_rdata & 0x01)==1);
cycle_count = 0;
return (0);
// Finished without Errors
}
/*
* Program Page in Flash Memory
* Parameter: adr: Page Start Address
* sz: Page Size
* buf: Page Data
* Return Value: 0 - OK, 1 - Failed
*/
FLASH_DRIVER_SEG int lega_flash_alg_programpage(unsigned long adr, unsigned long sz, unsigned char *buf)
{
unsigned long adr_temp,sz_temp;
int var_rdata = 0;
volatile int cycle_count = 0;
adr_temp = 0;
if((0 == sz) || (NULL == buf))
{
return 1;
}
sz_temp = sz - 1;
//word align
sz = (sz + 3) & ~3; // Adjust size for Words
//write one page data to Buffer
while (sz) {
M32(FLASH_BASE + 0x100 + adr_temp) = *((unsigned long *)buf); // Program Half Word
while((FLASH->BUSY & 0x01)==1){
}
buf += 4;
sz -= 4;
adr_temp +=4;
}
while((FLASH->BUSY & 0x01)==1);
//configure XTX mode, disable auto ERA nor PRG
FLASH->CFG = 0x200;
do
{ //write enable
FLASH->CMD = WREN;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read Device status register
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
var_rdata = FLASH->STATUS;//READ status
cycle_count++;
if(cycle_count == 5)
{
return adr;
}
}while(((var_rdata>>1) & 0x01 )==0);
cycle_count = 0;
//set command PP
FLASH->CMD = PP; //WRITE
FLASH->LENGTH = sz_temp;
FLASH->ADDR = adr;
FLASH->DUMMY = 0;
FLASH->SBUS_START = 0x01; //START WRITE
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
do
{ //set command Read Device status reg
FLASH->CMD = RDSR;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(30);
while((FLASH->BUSY & 0x01)==1);
//read flash controller status register
var_rdata = FLASH->STATUS;
//polling status register
cycle_count++;
//timeout check
if(cycle_count == 5000000)
{
return adr;
}
}while((var_rdata & 0x01)==1);
cycle_count = 0;
return (0); // Finished without Errors
}
#elif (defined LEGA_A0V2)
FLASH_DRIVER_SEG int lega_flash_alg_check_busy (void) {
int var_rdata = 0;
int cnt = 0;
/* Add your Code */
var_rdata = FLASH->QSPI_SR; //read back
while(((var_rdata>>5 & 0x01) ==1)){
var_rdata = FLASH->QSPI_SR; //read back
if(cnt < 80000000)//erase chip time(10s)/(160MHz*2cycle)
cnt = cnt+1;
else
return (1);
}
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_check_abort_busy (void) {
int var_rdata = 0;
int cnt = 0;
/* Add your Code */
var_rdata = FLASH->QSPI_SR; //read back
while(((var_rdata>>6 & 0x01) ==1)){
var_rdata = FLASH->QSPI_SR; //read back
if(cnt < 200)// /160MHz*10cycled
cnt = cnt+1;
else
return (1);
}
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_clr_flg (void) {
/* Add your Code */
FLASH->QSPI_FCR = 0xF001B;//0x1F;
FLASH->QSPI_FCR = 0x0;
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_abort_en (void) {
/* Add your Code */
int var_rdata;
var_rdata=FLASH->QSPI_CR;
FLASH->QSPI_CR = (var_rdata&0xFFFFFFFD)+0x2;
FLASH->QSPI_CR = var_rdata&0xFFFFFFFD;
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_polling_wip (void){
int var_rdata = 0;
//dumode=2'b00,fmode=2'b10,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h05;
FLASH->QSPI_CCR = 0x9000105;
var_rdata = FLASH->QSPI_CR;
FLASH->QSPI_CR = (var_rdata & 0xFFBFFFFF) + 0x400000; //QSPI_CR[22],apms= 1'b1;
FLASH->QSPI_DLR = 0x0;//one byte
FLASH->QSPI_PSMKR = 0x1;//mask = 0x1;
FLASH->QSPI_PSMAR = 0x0;//match = 0x0;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_clr_flg();
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_polling_wel (void){
int var_rdata = 0;
//dumode=2'b00,fmode=2'b10,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h05;
FLASH->QSPI_CCR = 0x9000105;
var_rdata = FLASH->QSPI_CR;
FLASH->QSPI_CR = (var_rdata & 0xFFBFFFFF) + 0x400000; //QSPI_CR[22],apms= 1'b1;
FLASH->QSPI_DLR = 0x0;//one byte
FLASH->QSPI_PSMKR = 0x2;//mask = 0x1;
FLASH->QSPI_PSMAR = 0x2;//match = 0x0;
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_clr_flg();
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG int lega_flash_alg_setqe (unsigned char quad) {
//bypass enable 0x4000308C bit10 set 1
//*((volatile unsigned int *)(0x4000308C)) |= (1 << 10);
FLASH->QSPI_CFGR |= (1 << 10);
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
FLASH->QSPI_CCR = 0x106;//IMODE=2'b01,INSTRUCTION=WREN
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_polling_wel();
FLASH->QSPI_CCR = 0x01000101;//dumode=2'b00,fmode=2'b00,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h01;
FLASH->QSPI_DLR = 0x1;//two byte
if(quad == 0x1){
FLASH->QSPI_DR = 0x200;
}
else{
FLASH->QSPI_DR = 0x0; //0x200;
}
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_clr_flg();
lega_flash_alg_polling_wip();
//bypass disable 0x4000308C bit10 clr
//*((volatile unsigned int *)(0x4000308C)) &= ~(1 << 10);
FLASH->QSPI_CFGR &= ~(1 << 10);
/* Add your Code */
return (0); // Finished without Errors
}
//use in unencryption
FLASH_DRIVER_SEG int lega_flash_alg_check_setqe (void) {
volatile int var_rdata = 0;
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
lega_flash_alg_check_busy();
FLASH->QSPI_DLR = 0x0;
FLASH->QSPI_CCR = 0x5000135;//dumode=2'b00,fmode=2'b01,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h35;
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
var_rdata = FLASH->QSPI_DR & 0xFF;
return var_rdata;
}
FLASH_DRIVER_SEG void lega_flash_alg_load_cfg () {
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
#ifdef CFG_CERTIF_TEST
FLASH->QSPI_CR = FLASH_QSPI_DIV4; //div4, //offset 0x00
#else
FLASH->QSPI_CR = FLASH_QSPI_DIV2; //div2, //offset 0x00
#endif
FLASH->QSPI_DCR = 0x00140000 ; //offset 0x04
FLASH->QSPI_FCR = 0x0 ; //offset 0x0C
FLASH->QSPI_DLR = 0x0 ; //offset 0x10
FLASH->QSPI_CCR = FLASH_QSPI_L2;//dumode=2'b10,,sio=1'b0,fmode=2'b11,dmode=2'b10,reserved=1'b0,dcyc=5'h7,absize=2'b00,abmode=2'b00,adsize=2'b10,admode=2'b01,imode=2'b01,instruction=8'h3B;
FLASH->QSPI_AR = 0x0 ; //offset 0x18
FLASH->QSPI_ABR = 0x0 ; //offset 0x1C
FLASH->QSPI_DR = 0x0 ; //offset 0x20
FLASH->QSPI_PSMKR = 0x0 ; //offset 0x24
FLASH->QSPI_PSMAR = 0x0 ; //offset 0x28
FLASH->QSPI_PIR = 0x0 ; //offset 0x2C
FLASH->QSPI_TOR = 0x12FFFF ; //offset 0x30
FLASH->QSPI_CFGR = 0x200 ; //offset 0x8C
}
// flash crypt bypass test
FLASH_DRIVER_SEG int lega_flash_alg_init ()
{
//add delay to avoid confilict between flash cfg and instruction fetch by cache
lega_flash_alg_f_delay(32);
//lega_flash_alg_abort_en();
//lega_flash_alg_check_abort_busy();
//lega_flash_alg_setqe(1);
lega_flash_alg_load_cfg ();
//flush cache after flash operation
lega_flash_alg_cache_flush();
return (0); // Finished without Errors
}
/*
* cmd: CHIP_ERASE_CMD or SECTOR_ERASE_CMD or BLOCK32_ERASE_CMD or BLOCK64_ERASE_CMD
* adr: not used for CHIP_ERASE_CMD
*/
FLASH_DRIVER_SEG int lega_flash_alg_erase(unsigned int cmd, unsigned long adr) {
//add delay to avoid confilict between flash cfg and instruction fetch by cache
lega_flash_alg_f_delay(32);
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
FLASH->QSPI_CCR = 0x106;//IMODE=2'b01,INSTRUCTION=WREN
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_polling_wel();
FLASH->QSPI_CCR = cmd;
if(CHIP_ERASE_CMD != cmd)
{
FLASH->QSPI_AR = adr;
}
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_clr_flg();
lega_flash_alg_polling_wip();
lega_flash_alg_f_delay(10);
lega_flash_alg_clr_flg();
lega_flash_alg_load_cfg();
//flush cache after flash operation
lega_flash_alg_cache_flush();
/* Add your Code */
return (0); // Finished without Errors
}
/*
* Program Page in Flash Memory
* Parameter: adr: Page Start Address
* sz: Page Size
* buf: Page Data
* Return Value: 0 - OK, 1 - Failed
*/
FLASH_DRIVER_SEG int lega_flash_alg_programpage(unsigned long adr, unsigned long sz, unsigned char *buf) {
unsigned long sz_temp;
//volatile int cycle_count = 0;
int var_rdata = 0;
int fthres = 8;
int cnt = 0;
if((0 == sz) || (NULL == buf))
{
return 1;
}
sz_temp = sz - 1;
sz = (sz + 3) & ~3; // Adjust size for Words
//add delay to avoid confilict between flash cfg and instruction fetch by cache
lega_flash_alg_f_delay(32);
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
FLASH->QSPI_CCR = 0x106;//IMODE=2'b01,INSTRUCTION=WREN
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_polling_wel();
FLASH->QSPI_CCR = 0x1002502;//fmode=2'b00,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b10,admode=2'b01,imode=2'b01,instruction=8'h02;
FLASH->QSPI_DLR = sz_temp;
FLASH->QSPI_AR = adr;
while ((sz>0)&&(cnt<fthres)) {
var_rdata = FLASH->QSPI_SR;
var_rdata = var_rdata >>8 & 0x3F;
if(var_rdata < fthres) {
FLASH->QSPI_DR = *((unsigned long *)buf); // Program Word
cnt += 1;
buf += 4;
sz -= 4;
}
}
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
FLASH->SBUS_START = 0x01; //WRITE
lega_flash_alg_f_delay(10);
while (sz) {
var_rdata = FLASH->QSPI_SR;
var_rdata = var_rdata >>8 & 0x3F;
if(var_rdata < fthres) {
FLASH->QSPI_DR = *((unsigned long *)buf); // Program Word
buf += 4;
sz -= 4;
}
}
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
lega_flash_alg_polling_wip();
lega_flash_alg_load_cfg ();
//flush cache after flash operation
lega_flash_alg_cache_flush();
return (0); // Finished without Errors
}
FLASH_DRIVER_SEG void lega_flash_alg_read_buf_clr(void)
{
#if 0
unsigned int tmp = REG_RD(FLASH_BASE);
REG_WR(FLASH_BASE, tmp & (~0x1));
REG_WR(FLASH_BASE, tmp);
#else
unsigned int tmp = FLASH->QSPI_CR;
FLASH->QSPI_CR = tmp & (~0x1);
FLASH->QSPI_CR = tmp;
#endif
}
#ifdef _SPI_FLASH_120MHz_
FLASH_DRIVER_SEG void lega_flash_alg_set_clk_120(unsigned char en_120m)
{
if (en_120m)
REG_WR(CLK_FLASH_SEL,FLASH_120_CLK);
else
REG_WR(CLK_FLASH_SEL,FLASH_52_CLK);
}
#endif
#ifdef _SPI_FLASH_240MHz_
FLASH_DRIVER_SEG int lega_flash_alg_read_id(void){
int var_rdata;
int dshift;
lega_flash_alg_abort_en();
lega_flash_alg_check_abort_busy();
FLASH->QSPI_CCR = 0x500019F;//fmode=2'b01,dmode=2'b01,reserved=1'b0,dcyc=5'h0,absize=2'b00,abmode=2'b00,adsize=2'b00,admode=2'b00,imode=2'b01,instruction=8'h9F;
FLASH->QSPI_DLR = 0x2;
lega_flash_alg_clr_flg();
FLASH->SBUS_START = 0x1;
lega_flash_alg_f_delay(10);
lega_flash_alg_check_busy();
var_rdata = FLASH->QSPI_CR;
dshift = (var_rdata>>13)&0x7;
lega_flash_alg_f_delay(dshift);
var_rdata = FLASH->QSPI_DR;
lega_flash_alg_load_cfg();
return(var_rdata);
}
FLASH_DRIVER_SEG void lega_flash_alg_calibrate_shift(int prescaler)
{
volatile int delay_shift = 0;
volatile int sshift = 0;
unsigned int rdata;
unsigned int wdata;
unsigned int identi;
volatile int id, mem_type, capacity;
int i = 0;
int sshift_max[8]={0};
int sshift_min[8]={0};
int match_flag[8]={0};
int match_interval[8] = {0};
//*(volatile int *)(0x40000808) = 0x2;
REG_WR(CLK_FLASH_SEL,FLASH_240_CLK);
for(delay_shift = 0; delay_shift < 8; delay_shift = delay_shift +1)
{
sshift_max[delay_shift]=0;
sshift_min[delay_shift]=0;
for(sshift = 0; sshift < prescaler; sshift = sshift +1)
{
rdata = FLASH->QSPI_CR;
wdata = rdata&0x87FF1FFF;
wdata |= (sshift&0xF) <<27;
wdata |= (delay_shift&0x7) <<13;
FLASH->QSPI_CR = wdata;
//read_id
identi = lega_flash_alg_read_id();
id = identi&0xFF;
mem_type = (identi&0xFF00)>>8;
capacity = (identi&0xFF0000)>>16;
if(id == 0x0B && mem_type == 0x40 && capacity == 0x15)
{
match_flag[delay_shift]=0x1;
if(sshift_max[delay_shift] < sshift)
sshift_max[delay_shift] = sshift;
if(sshift_min[delay_shift] > sshift)
sshift_min[delay_shift]=sshift;
}
else
{
sshift_min[delay_shift]=sshift + 1;
if(sshift_min[delay_shift]==prescaler)
{
sshift_min[delay_shift] = 0;
}
}
}
}
for(i = 0;i< 8;i++)
{
if(match_flag[i] == 1)
match_interval[i]= sshift_max[i]-sshift_min[i]+1;
else{
match_interval[i] = 0;
}
}
//get the best delay_shift(means max mactch_interval
delay_shift = 0;
for(i = 1;i < 8;i = i+1)
{
if(match_interval[i] > match_interval[delay_shift])
{
delay_shift = i;
}
}
sshift = (sshift_max[delay_shift] + sshift_min[delay_shift])/2 + (sshift_max[delay_shift] + sshift_min[delay_shift])%2;
rdata = FLASH->QSPI_CR;
wdata = rdata&0x87FF1FFF;
wdata |= (sshift&0xF) <<27;
wdata |= (delay_shift&0x7) <<13;
FLASH->QSPI_CR = wdata;
}
#endif
#endif

View file

@ -0,0 +1,544 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_gpio.h"
lega_gpio_cb_t g_lega_gpio_handler[LEGA_GPIO_TOTAL_NUM];
//gpio pinmux function table
const uint32_t GPIO_PINMUX_FUN[LEGA_GPIO_TOTAL_NUM] =
{
#if (defined LEGA_A0V1)
0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
#elif (defined LEGA_A0V2)
0, 0, 0, 0, 1, 1, 0, 0,
0, 0, 2, 0, 0, 0, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0
#endif
};
void GPIO_IRQHandler(void)
{
lega_intrpt_enter();
for(int i = 0; i < LEGA_GPIO_TOTAL_NUM; i++)
{
if(i < LEGA_GPIO_NUM_PER_GROUP)
{
//gpio group0 irq
if(GPIO_GROUP0->INTSTATUS & (0x0001 << i))
{
//clear GPIO GROUP0 interrupt
GPIO_GROUP0->INTSTATUS = (0x0001 << i);
if(g_lega_gpio_handler[i].cb)
{
g_lega_gpio_handler[i].cb(g_lega_gpio_handler[i].arg);
}
}
}
else
{
//gpio group1 irq
if(GPIO_GROUP1->INTSTATUS & (0x0001 << (i-LEGA_GPIO_NUM_PER_GROUP)))
{
//clear GPIO GROUP1 interrupt
GPIO_GROUP1->INTSTATUS = (0x0001 << (i-LEGA_GPIO_NUM_PER_GROUP));
if(g_lega_gpio_handler[i].cb)
{
g_lega_gpio_handler[i].cb(g_lega_gpio_handler[i].arg);
}
}
}
}
lega_intrpt_exit();
}
/**
* Initialises a GPIO pin
*
* @note Prepares a GPIO pin for use.
*
* @param[in] gpio the gpio pin which should be initialised
* @param[in] configuration A structure containing the required gpio configuration
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_init(lega_gpio_dev_t *gpio)
{
uint32_t reg_value;
if(NULL == gpio)
{
return -1;
}
//pinmux setting
if(gpio->port < 8)
{
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~(0x0000000F << (4*gpio->port)));
REG_WR(PINMUX_CTRL_REG0, (reg_value|(GPIO_PINMUX_FUN[gpio->port] << (4*gpio->port))));
}
else if(gpio->port < 16)
{
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~(0x0000000F << (4*(gpio->port-8))));
REG_WR(PINMUX_CTRL_REG1, (reg_value|(GPIO_PINMUX_FUN[gpio->port] << (4*(gpio->port-8)))));
}
else if(gpio->port < 24)
{
reg_value = REG_RD(PINMUX_CTRL_REG2) & (~(0x0000000F << (4*(gpio->port-16))));
REG_WR(PINMUX_CTRL_REG2, (reg_value|(GPIO_PINMUX_FUN[gpio->port] << (4*(gpio->port-16)))));
}
#if (defined LEGA_A0V1)
else if(gpio->port < 32)
{
reg_value = REG_RD(PINMUX_CTRL_REG3) & (~(0x0000000F << (4*(gpio->port-24))));
REG_WR(PINMUX_CTRL_REG3, (reg_value|(GPIO_PINMUX_FUN[gpio->port] << (4*(gpio->port-24)))));
}
#endif
else
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
switch(gpio->config)
{
case LEGA_ANALOG_MODE:
break;
case LEGA_IRQ_MODE:
case LEGA_INPUT_PULL_UP:
if(GPIO_GROUP0->OUTENSET & (1 << gpio->port))
{
GPIO_GROUP0->OUTENCLR = (1 << gpio->port);
}
#if (defined LEGA_A0V2)
reg_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (reg_value & (~(1 << gpio->port))));
#endif
reg_value = REG_RD(PAD_PS_REG);
REG_WR(PAD_PS_REG, (reg_value | (1 << gpio->port)));
reg_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (reg_value | (1 << gpio->port)));
break;
case LEGA_INPUT_PULL_DOWN:
if(GPIO_GROUP0->OUTENSET & (1 << gpio->port))
{
GPIO_GROUP0->OUTENCLR = (1 << gpio->port);
}
#if (defined LEGA_A0V2)
reg_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (reg_value & (~(1 << gpio->port))));
#endif
reg_value = REG_RD(PAD_PS_REG);
REG_WR(PAD_PS_REG, (reg_value & (~(1 << gpio->port))));
reg_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (reg_value | (1 << gpio->port)));
break;
case LEGA_INPUT_HIGH_IMPEDANCE:
if(GPIO_GROUP0->OUTENSET & (1 << gpio->port))
{
GPIO_GROUP0->OUTENCLR = (1 << gpio->port);
}
break;
case LEGA_OUTPUT_PUSH_PULL:
case LEGA_OUTPUT_OPEN_DRAIN_NO_PULL:
case LEGA_OUTPUT_OPEN_DRAIN_PULL_UP:
if(!(GPIO_GROUP0->OUTENSET & (1 << gpio->port)))
{
GPIO_GROUP0->OUTENSET = (1 << gpio->port);
}
break;
default:
return -1;
//break;
}
}
else //if(gpio->port < 32/24)
{
switch(gpio->config)
{
case LEGA_ANALOG_MODE:
break;
case LEGA_IRQ_MODE:
break;
case LEGA_INPUT_PULL_UP:
if(GPIO_GROUP1->OUTENSET & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP)))
{
GPIO_GROUP1->OUTENCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
#if (defined LEGA_A0V2)
reg_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (reg_value & (~(1 << gpio->port))));
#endif
reg_value = REG_RD(PAD_PS_REG);
REG_WR(PAD_PS_REG, (reg_value | (1 << gpio->port)));
reg_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (reg_value | (1 << gpio->port)));
break;
case LEGA_INPUT_PULL_DOWN:
if(GPIO_GROUP1->OUTENSET & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP)))
{
GPIO_GROUP1->OUTENCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
#if (defined LEGA_A0V2)
reg_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (reg_value & (~(1 << gpio->port))));
#endif
reg_value = REG_RD(PAD_PS_REG);
REG_WR(PAD_PS_REG, (reg_value & (~(1 << gpio->port))));
reg_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (reg_value | (1 << gpio->port)));
break;
case LEGA_INPUT_HIGH_IMPEDANCE:
if(GPIO_GROUP1->OUTENSET & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP)))
{
GPIO_GROUP1->OUTENCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
break;
case LEGA_OUTPUT_PUSH_PULL:
case LEGA_OUTPUT_OPEN_DRAIN_NO_PULL:
case LEGA_OUTPUT_OPEN_DRAIN_PULL_UP:
if(!(GPIO_GROUP1->OUTENSET & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP))))
{
GPIO_GROUP1->OUTENSET = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
break;
default:
return -1;
//break;
}
}
return 0;
}
/**
* Sets an output GPIO pin high
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set high
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_high(lega_gpio_dev_t *gpio)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
GPIO_GROUP0->DATAOUT |= (1 << gpio->port);
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
GPIO_GROUP1->DATAOUT |= (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
else
{
return -1;
}
return 0;
}
/**
* Sets an output GPIO pin low
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_low(lega_gpio_dev_t *gpio)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
GPIO_GROUP0->DATAOUT &= ~(1 << gpio->port);
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
GPIO_GROUP1->DATAOUT &= ~(1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
else
{
return -1;
}
return 0;
}
/**
* Get the state of an output GPIO pin. Using this function on a
* gpio pin which is set to input mode will return an undefined value.
*
* @param[in] gpio the gpio pin which should be read
* @param[in] value gpio value
*
* @return 0 : on success, EIO : if an error occurred with any step
*
* note: defined by asr
*/
int32_t lega_gpio_output_get(lega_gpio_dev_t *gpio, uint32_t *value)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
*value = (GPIO_GROUP0->DATAOUT >> (gpio->port)) & 1;
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
*value = (GPIO_GROUP1->DATAOUT >> ((gpio->port-LEGA_GPIO_NUM_PER_GROUP))) & 1;
}
else
{
return -1;
}
return 0;
}
/**
* Trigger an output GPIO pin's output. Using this function on a
* gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_output_toggle(lega_gpio_dev_t *gpio)
{
uint32_t value;
if(NULL == gpio)
{
return -1;
}
if(0 == lega_gpio_output_get(gpio, &value))
{
if(value)
{
return lega_gpio_output_low(gpio);
}
else
{
return lega_gpio_output_high(gpio);
}
}
else
{
return -1;
}
}
/**
* Get the state of an input GPIO pin. Using this function on a
* gpio pin which is set to output mode will return an undefined value.
*
* @param[in] gpio the gpio pin which should be read
* @param[in] value gpio value
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_input_get(lega_gpio_dev_t *gpio, uint32_t *value)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
*value = (GPIO_GROUP0->DATA >> gpio->port) & 1;
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
*value = (GPIO_GROUP1->DATA >> (gpio->port-LEGA_GPIO_NUM_PER_GROUP)) & 1;
}
else
{
return -1;
}
return 0;
}
/**
* Enables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which is set to
* output mode is undefined.
*
* @param[in] gpio the gpio pin which will provide the interrupt trigger
* @param[in] trigger the type of trigger (rising/falling edge)
* @param[in] handler a function pointer to the interrupt handler
* @param[in] arg an argument that will be passed to the interrupt handler
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_enable_irq(lega_gpio_dev_t *gpio, lega_gpio_irq_trigger_t trigger,
lega_gpio_irq_handler_t handler, void *arg)
{
if(NULL == gpio)
{
return -1;
}
g_lega_gpio_handler[gpio->port].cb = handler;
g_lega_gpio_handler[gpio->port].arg = arg;
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
switch(trigger)
{
case LEGA_IRQ_TRIGGER_RISING_EDGE:
GPIO_GROUP0->INTTYPESET = (1 << gpio->port); //edge or level trig
GPIO_GROUP0->INTPOLSET = (1 << gpio->port); //trig polarity
break;
case LEGA_IRQ_TRIGGER_FALLING_EDGE:
GPIO_GROUP0->INTTYPESET = (1 << gpio->port);
GPIO_GROUP0->INTPOLCLR = (1 << gpio->port);
break;
case LEGA_IRQ_TRIGGER_BOTH_EDGES:
default:
return -1;
}
GPIO_GROUP0->INTENSET = (1 << gpio->port); //int enable
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
switch(trigger)
{
case LEGA_IRQ_TRIGGER_RISING_EDGE:
GPIO_GROUP1->INTTYPESET = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
GPIO_GROUP1->INTPOLSET = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
break;
case LEGA_IRQ_TRIGGER_FALLING_EDGE:
GPIO_GROUP1->INTTYPESET = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
GPIO_GROUP1->INTPOLCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
break;
case LEGA_IRQ_TRIGGER_BOTH_EDGES:
default:
return -1;
}
GPIO_GROUP1->INTENSET = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
else
{
return -1;
}
NVIC_EnableIRQ(GPIO_IRQn); //0x10
return 0;
}
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref lega_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_disable_irq(lega_gpio_dev_t *gpio)
{
if(NULL == gpio)
{
return -1;
}
g_lega_gpio_handler[gpio->port].cb = NULL;
g_lega_gpio_handler[gpio->port].arg = NULL;
//NVIC_DisableIRQ(GPIO_IRQn); //common use
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
GPIO_GROUP0->INTENCLR = (1 << gpio->port);
GPIO_GROUP0->INTTYPECLR = (1 << gpio->port);
GPIO_GROUP0->INTPOLCLR = (1 << gpio->port);
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
GPIO_GROUP1->INTTYPECLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
GPIO_GROUP1->INTPOLCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
GPIO_GROUP1->INTENCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
else
{
return -1;
}
return 0;
}
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref lega_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_clear_irq(lega_gpio_dev_t *gpio)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
//GPIO interrupt status
if(GPIO_GROUP0->INTSTATUS & (1 << gpio->port))
{
//clear GPIO interrupt status
GPIO_GROUP0->INTSTATUS = (1 << gpio->port);
}
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
if(GPIO_GROUP1->INTSTATUS & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP)))
{
GPIO_GROUP1->INTSTATUS = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
}
else
{
return -1;
}
return 0;
}
/**
* Set a GPIO pin in default state.
*
* @param[in] gpio the gpio pin which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_gpio_finalize(lega_gpio_dev_t *gpio)
{
if(NULL == gpio)
{
return -1;
}
if(gpio->port < LEGA_GPIO_NUM_PER_GROUP)
{
if(GPIO_GROUP0->OUTENSET & (1 << gpio->port))
{
GPIO_GROUP0->OUTENCLR = (1 << gpio->port);
}
}
else if(gpio->port < LEGA_GPIO_TOTAL_NUM)
{
if(GPIO_GROUP1->OUTENSET & (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP)))
{
GPIO_GROUP1->OUTENCLR = (1 << (gpio->port-LEGA_GPIO_NUM_PER_GROUP));
}
}
else
{
return -1;
}
lega_gpio_disable_irq(gpio);
lega_gpio_clear_irq(gpio);
return 0;
}

View file

@ -0,0 +1,850 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_i2c.h"
#include "lega_timer.h"
lega_i2c_slv_callback_t g_lega_i2c_slv_callback_handler[LEGA_I2C_NUM];
lega_timer_dev_t g_lega_timer1;
volatile int g_lega_i2c_timeout = 0;
void I2C0_IRQHandler(void)
{
lega_intrpt_enter();
uint8_t rx_data;
if(I2C0->IC_INTR_STAT & RD_REQ)
{
if(I2C0->IC_RAW_INTR_STAT & TX_ABRT)
{
I2C0->IC_CLR_TX_ABRT; //clear interrupt
}
I2C0->IC_CLR_RD_REG; //clear interrupt
if(g_lega_i2c_slv_callback_handler[I2C_DEVICE0].tx_func)
{
g_lega_i2c_slv_callback_handler[I2C_DEVICE0].tx_func();
}
}
if(I2C0->IC_INTR_STAT & RX_FULL)
{
rx_data = I2C0->IC_DATA_CMD & 0xFF;
if(g_lega_i2c_slv_callback_handler[I2C_DEVICE0].rx_func)
{
g_lega_i2c_slv_callback_handler[I2C_DEVICE0].rx_func(rx_data);
}
}
lega_intrpt_exit();
}
void I2C1_IRQHandler(void)
{
lega_intrpt_enter();
uint8_t rx_data;
if(I2C1->IC_INTR_STAT & RD_REQ)
{
if(I2C1->IC_RAW_INTR_STAT & TX_ABRT)
{
I2C1->IC_CLR_TX_ABRT; //clear interrupt
}
I2C1->IC_CLR_RD_REG; //clear interrupt
if(g_lega_i2c_slv_callback_handler[I2C_DEVICE1].tx_func)
{
g_lega_i2c_slv_callback_handler[I2C_DEVICE1].tx_func();
}
}
if(I2C1->IC_INTR_STAT & RX_FULL)
{
rx_data = I2C1->IC_DATA_CMD & 0xFF;
if(g_lega_i2c_slv_callback_handler[I2C_DEVICE1].rx_func)
{
g_lega_i2c_slv_callback_handler[I2C_DEVICE1].rx_func(rx_data);
}
}
lega_intrpt_exit();
}
int32_t lega_i2c_reset(lega_i2c_dev_t *i2c)
{
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
REG_WR(I2C0_SW_RESET_REG, 1);
delay(10);
REG_WR(I2C0_SW_RESET_REG, 0);
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
REG_WR(I2C1_SW_RESET_REG, 1);
delay(10);
REG_WR(I2C1_SW_RESET_REG, 0);
}
else
{
return -1;
}
return 0;
}
/**
* Initialises an I2C interface
* Prepares an I2C hardware interface for communication as a master or slave
*
* @param[in] i2c the device for which the i2c port should be initialised
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_init(lega_i2c_dev_t *i2c)
{
uint32_t reg_value;
I2C_TypeDef *I2Cx;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
//pinmux cfg
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
#if (0 == I2C_PAD_GROUP) // set pad2:3 for i2c0 func 4
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~I2C0_PINMUX_MASK0);
REG_WR(PINMUX_CTRL_REG0, (reg_value|I2C0_PINMUX_VALUE0));
#else // set pad20:21 for i2c0 scl/sda func 1
reg_value = REG_RD(PINMUX_CTRL_REG2) & (~I2C0_PINMUX_MASK1);
REG_WR(PINMUX_CTRL_REG2, (reg_value|I2C0_PINMUX_VALUE1));
#endif
}
else // I2C_DEVICE1
{
#if (0 == I2C_PAD_GROUP) // set pad 8:9 for i2c1 func 3
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~I2C1_PINMUX_MASK0);
REG_WR(PINMUX_CTRL_REG1, (reg_value|I2C1_PINMUX_VALUE0));
#else // set pad22:23 for i2c1 scl/sda func 1
reg_value = REG_RD(PINMUX_CTRL_REG2) & (~I2C1_PINMUX_MASK1);
REG_WR(PINMUX_CTRL_REG2, (reg_value|I2C1_PINMUX_VALUE1));
#endif
}
//i2c clk enable
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
//I2C0 clock enable
reg_value = REG_RD(I2C0_CLK_CFG);
REG_WR(I2C0_CLK_CFG, (reg_value|I2C0_CLK_EN));
}
else // I2C_DEVICE1
{
//I2C1 clock enable
reg_value = REG_RD(I2C1_CLK_CFG);
REG_WR(I2C1_CLK_CFG, (reg_value|I2C1_CLK_EN));
}
I2Cx->IC_ENABLE = 0;
while(I2Cx->IC_ENABLE_STATUS & 0x01);
if(I2C_MODE_MASTER == i2c->config.mode) //master mode
{
if(i2c->config.freq <= I2C_SS_MAX_SCL_FREQ) // standard mode 100k
{
I2Cx->IC_SS_SCL_HCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 12); //SS_SCL_HCNT; //set i2c clock timing
I2Cx->IC_SS_SCL_LCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 1); //SS_SCL_LCNT; //set i2c clock timing
I2Cx->IC_CON = (IC_CON_SS_MODE);
}
else if(i2c->config.freq <= I2C_FS_PLUS_MAX_SCL_FREQ) // fast mode 400k, fast mode plus 1m
{
I2Cx->IC_FS_SCL_HCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 12); //FS_SCL_HCNT; //set i2c clock timing
I2Cx->IC_FS_SCL_LCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 1); //FS_SCL_LCNT; //set i2c clock timing
I2Cx->IC_CON = (IC_CON_FS_MODE);
}
else if(i2c->config.freq <= I2C_HS_MAX_SCL_FREQ) // high speed 3.4m
{
I2Cx->IC_HS_SCL_HCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 8); //HS_SCL_HCNT; //set i2c clock timing
I2Cx->IC_HS_SCL_LCNT = (SYSTEM_CLOCK/2/i2c->config.freq - 1); //HS_SCL_LCNT; //set i2c clock timing
I2Cx->IC_HS_MADDR = MASTER_CODE; //set master code: 0x0F(8 + IC_HS_MADDR)
I2Cx->IC_CON = (IC_CON_HS_MODE);
}
else
{
}
if(I2C_ADDR_WIDTH_10BIT == i2c->config.address_width)
{
I2Cx->IC_CON |= (IC_CON_IC_10BITADDR_MASTER);
}
I2Cx->IC_CON |= (IC_CON_MASTER_MODE | IC_CON_IC_RESTART_EN | IC_SLAVE_DISABLE | IC_CON_RX_FIFO_FULL_HLD_CTRL);
#if 1
I2Cx->IC_INTR_MASK = 0; //M_RX_FULL; //0x04; //enable RX_FULL -- 1: unmask interrupt 0: mask interrupt
#endif
}
else //slave mode
{
if(i2c->config.freq <= I2C_SS_MAX_SCL_FREQ) // standard mode 100k
{
I2Cx->IC_CON = (IC_CON_SS_MODE);
}
else if(i2c->config.freq <= I2C_FS_PLUS_MAX_SCL_FREQ) // fast mode 400k, fast mode plus 1m
{
I2Cx->IC_CON = (IC_CON_FS_MODE);
}
else if(i2c->config.freq <= I2C_HS_MAX_SCL_FREQ) // high speed 3.4m
{
I2Cx->IC_CON = (IC_CON_HS_MODE);
}
else
{
}
if(I2C_ADDR_WIDTH_7BIT == i2c->config.address_width)
{
I2Cx->IC_SAR = i2c->config.dev_addr;
}
else
{
I2Cx->IC_SAR = i2c->config.dev_addr;
I2Cx->IC_CON |= (IC_CON_IC_10BITADDR_SLAVE);
}
I2Cx->IC_CON |= (IC_CON_IC_RESTART_EN | IC_CON_RX_FIFO_FULL_HLD_CTRL);
#if 1
I2Cx->IC_INTR_MASK = (M_RX_FULL | M_RD_REQ); //0x24; //enable RX_FULL and RD_REQ
#endif
if(i2c->priv)
{
g_lega_i2c_slv_callback_handler[i2c->port].tx_func = ((lega_i2c_slv_callback_t *)(i2c->priv))->tx_func;
g_lega_i2c_slv_callback_handler[i2c->port].rx_func = ((lega_i2c_slv_callback_t *)(i2c->priv))->rx_func;
}
}
I2Cx->IC_RX_TL = 0;
I2Cx->IC_TX_TL = 0;
I2Cx->IC_ENABLE = 1;
while(!(I2Cx->IC_ENABLE_STATUS & 0x01));
#if 1
//TODO: I2C interrupt enable should be put before I2C enable
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
NVIC_EnableIRQ(I2C0_IRQn); //enable I2C0 interrupt
}
else
{
NVIC_EnableIRQ(I2C1_IRQn); //enable I2C1 interrupt
}
#endif
return 0;
}
void lega_timer1_irq_handler(void *arg)
{
g_lega_i2c_timeout = 1;
}
/**
* I2c master send
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] data i2c send data
* @param[in] size i2c send data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_master_send(lega_i2c_dev_t *i2c, uint16_t dev_addr, const uint8_t *data,
uint16_t size, uint32_t timeout)
{
//master write data
I2C_TypeDef *I2Cx;
uint16_t i = 0;
int ret = 0;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
//set target addr
if(I2C_ADDR_WIDTH_7BIT == i2c->config.address_width)
{
I2Cx->IC_TAR = dev_addr & 0x00FF;
}
else
{
I2Cx->IC_TAR = dev_addr;
}
if(0xFFFFFFFF != timeout)
{
g_lega_timer1.port = LEGA_TIMER1_INDEX;
g_lega_timer1.config.reload_mode = TIMER_RELOAD_MANU;
g_lega_timer1.config.cb = lega_timer1_irq_handler;
g_lega_timer1.config.arg = NULL;
g_lega_timer1.config.period = timeout*1000; //us
lega_timer_init(&g_lega_timer1);
g_lega_i2c_timeout = 0;
lega_timer_start(&g_lega_timer1);
}
while(i < size)
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
if((size-1) == i)
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_STOP | IC_DATA_CMD_WRITE | data[i++]);
}
else
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_WRITE | data[i++]);
}
}
}
while(!(I2Cx->IC_RAW_INTR_STAT & M_STOP_DET))
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
EXIT:
if(0xFFFFFFFF != timeout)
{
lega_timer_finalize(&g_lega_timer1);
}
return ret;
}
/**
* I2c master recv
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[out] data i2c receive data
* @param[in] size i2c receive data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_master_recv(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint8_t *data,
uint16_t size, uint32_t timeout)
{
//master read data
I2C_TypeDef *I2Cx;
uint16_t i = 0;
int ret = 0;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
//set target addr
if(I2C_ADDR_WIDTH_7BIT == i2c->config.address_width)
{
I2Cx->IC_TAR = dev_addr & 0x00FF;
}
else
{
I2Cx->IC_TAR = dev_addr;
}
if(0xFFFFFFFF != timeout)
{
g_lega_timer1.port = LEGA_TIMER1_INDEX;
g_lega_timer1.config.reload_mode = TIMER_RELOAD_MANU;
g_lega_timer1.config.cb = lega_timer1_irq_handler;
g_lega_timer1.config.arg = NULL;
g_lega_timer1.config.period = timeout*1000; //us
lega_timer_init(&g_lega_timer1);
g_lega_i2c_timeout = 0;
lega_timer_start(&g_lega_timer1);
}
while(i < size)
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
if((size-1) == i)
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_STOP | IC_DATA_CMD_READ);
}
else
{
I2Cx->IC_DATA_CMD = IC_DATA_CMD_READ;
}
while(!(I2Cx->IC_RAW_INTR_STAT & RX_FULL))
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
*(data+i) = I2Cx->IC_DATA_CMD & 0xFF;
i++;
}
}
while(!(I2Cx->IC_RAW_INTR_STAT & M_STOP_DET))
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
EXIT:
if(0xFFFFFFFF != timeout)
{
lega_timer_finalize(&g_lega_timer1);
}
return ret;
}
/**
* I2c mem write
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[in] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_mem_write(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, const uint8_t *data, uint16_t size,
uint32_t timeout)
{
//master write data
I2C_TypeDef *I2Cx;
uint16_t i = 0;
int ret = 0;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
if(I2C_ADDR_WIDTH_7BIT == i2c->config.address_width)
{
I2Cx->IC_TAR = dev_addr & 0x00FF;
}
else
{
I2Cx->IC_TAR = dev_addr;
}
if(0xFFFFFFFF != timeout)
{
g_lega_timer1.port = LEGA_TIMER1_INDEX;
g_lega_timer1.config.reload_mode = TIMER_RELOAD_MANU;
g_lega_timer1.config.cb = lega_timer1_irq_handler;
g_lega_timer1.config.arg = NULL;
g_lega_timer1.config.period = timeout*1000; //us
lega_timer_init(&g_lega_timer1);
g_lega_i2c_timeout = 0;
lega_timer_start(&g_lega_timer1);
}
while(i < mem_addr_size) //I2C_MEM_ADDR_SIZE_8BIT or I2C_MEM_ADDR_SIZE_16BIT
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_WRITE | ((mem_addr >> (8*i++)) & 0x00FF));
}
}
i = 0;
while(i < size)
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
if((size-1) == i)
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_STOP | IC_DATA_CMD_WRITE | data[i++]);
}
else
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_WRITE | data[i++]);
}
}
}
while(!(I2Cx->IC_RAW_INTR_STAT & M_STOP_DET))
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
EXIT:
if(0xFFFFFFFF != timeout)
{
lega_timer_finalize(&g_lega_timer1);
}
return ret;
}
/**
* I2c master mem read
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[out] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t lega_i2c_mem_read(lega_i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, uint8_t *data, uint16_t size,
uint32_t timeout)
{
//combined format
I2C_TypeDef *I2Cx;
uint16_t i = 0;
int ret = 0;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
if(I2C_ADDR_WIDTH_7BIT == i2c->config.address_width)
{
I2Cx->IC_TAR = dev_addr & 0x00FF;
}
else
{
I2Cx->IC_TAR = dev_addr;
}
if(0xFFFFFFFF != timeout)
{
g_lega_timer1.port = LEGA_TIMER1_INDEX;
g_lega_timer1.config.reload_mode = TIMER_RELOAD_MANU;
g_lega_timer1.config.cb = lega_timer1_irq_handler;
g_lega_timer1.config.arg = NULL;
g_lega_timer1.config.period = timeout*1000; //us
lega_timer_init(&g_lega_timer1);
g_lega_i2c_timeout = 0;
lega_timer_start(&g_lega_timer1);
}
while(i < mem_addr_size) //I2C_MEM_ADDR_SIZE_8BIT or I2C_MEM_ADDR_SIZE_16BIT
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_WRITE | ((mem_addr >> (8*i++)) & 0x00FF));
}
}
i = 0;
while(i < size)
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
if(I2Cx->IC_STATUS & TFNF)
{
//master send read cmd
if(0 == i)
{
I2Cx->IC_DATA_CMD = IC_DATA_CMD_RESTART | IC_DATA_CMD_READ; //IC_DATA_CMD_RESTART can be omit
}
else if((size - 1) == i)
{
I2Cx->IC_DATA_CMD = IC_DATA_CMD_STOP | IC_DATA_CMD_READ;
}
else
{
I2Cx->IC_DATA_CMD = IC_DATA_CMD_READ;
}
//master read data
while(!(I2Cx->IC_RAW_INTR_STAT & RX_FULL))
{
if(I2Cx->IC_RAW_INTR_STAT & TX_ABRT)
{
//clr TX_ABRT sts
//The TX FIFO remains in flushed state until the register IC_CLR_TX_ABRT is read
I2Cx->IC_CLR_TX_ABRT;
ret = -2;
goto EXIT;
}
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
*(data+i) = I2Cx->IC_DATA_CMD & 0xFF;
i++;
}
}
while(!(I2Cx->IC_RAW_INTR_STAT & M_STOP_DET))
{
if(g_lega_i2c_timeout)
{
g_lega_i2c_timeout = 0;
ret = -1;
goto EXIT;
}
}
EXIT:
if(0xFFFFFFFF != timeout)
{
lega_timer_finalize(&g_lega_timer1);
}
return ret;
}
int32_t lega_i2c_tx_data(lega_i2c_dev_t *i2c, uint8_t data)
{
I2C_TypeDef *I2Cx;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
I2Cx->IC_DATA_CMD = (IC_DATA_CMD_WRITE | data);
return 0;
}
/**
* Deinitialises an I2C device
*
* @param[in] i2c the i2c device
*
* @return 0 : on success, EIO : if an error occurred during deinitialisation
*/
int32_t lega_i2c_finalize(lega_i2c_dev_t *i2c)
{
I2C_TypeDef *I2Cx;
uint32_t reg_value;
if(NULL == i2c)
{
return -1;
}
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
I2Cx = I2C0;
}
else if(I2C_DEVICE1 == i2c->port) // I2C_DEVICE1
{
I2Cx = I2C1;
}
else
{
return -1;
}
//i2c clk disable
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
//I2C0 clock disable
reg_value = REG_RD(I2C0_CLK_CFG);
REG_WR(I2C0_CLK_CFG, (reg_value&(~I2C0_CLK_EN)));
}
else // I2C_DEVICE1
{
//I2C1 clock disable
reg_value = REG_RD(I2C1_CLK_CFG);
REG_WR(I2C1_CLK_CFG, (reg_value&(~I2C1_CLK_EN)));
}
// disable i2c cm4 irq
if(I2C_DEVICE0 == i2c->port) // I2C_DEVICE0
{
NVIC_DisableIRQ(I2C0_IRQn); //disable I2C0 interrupt
}
else
{
NVIC_DisableIRQ(I2C1_IRQn); //disable I2C1 interrupt
}
//callback function pointer clear
g_lega_i2c_slv_callback_handler[i2c->port].tx_func = NULL;
g_lega_i2c_slv_callback_handler[i2c->port].rx_func = NULL;
I2Cx->IC_ENABLE = 0;
while(I2Cx->IC_ENABLE_STATUS & 0x01);
return 0;
}

View file

@ -0,0 +1,293 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_pwm.h"
void PWM_IRQHandler(void)
{
lega_intrpt_enter();
lega_intrpt_exit();
}
//pwm pinmux init
void lega_pwm_pinmux_init(lega_pwm_dev_t *pwm)
{
uint32_t reg_value;
switch(pwm->port)
{
case PWM_OUTPUT_CH0:
//pin mux control
//PWM0_PAD PAD14 1
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~PWM0_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG1, (reg_value|PWM0_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH1:
//PWM1_PAD PAD10 1
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~PWM1_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG1, (reg_value|PWM1_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH2:
//PWM2_PAD PAD15 1
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~PWM2_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG1, (reg_value|PWM2_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH3:
//PWM3_PAD PAD11 1
reg_value = REG_RD(PINMUX_CTRL_REG1) & (~PWM3_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG1, (reg_value|PWM3_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH4:
//PWM4_PAD PAD6 4
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~PWM4_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG0, (reg_value|PWM4_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH5:
//PWM5_PAD PAD0 4
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~PWM5_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG0, (reg_value|PWM5_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH6:
//PWM6_PAD PAD7 4
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~PWM6_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG0, (reg_value|PWM6_PINMUX_VALUE));
break;
case PWM_OUTPUT_CH7:
//PWM7_PAD PAD1 4
reg_value = REG_RD(PINMUX_CTRL_REG0) & (~PWM7_PINMUX_MASK);
REG_WR(PINMUX_CTRL_REG0, (reg_value|PWM7_PINMUX_VALUE));
break;
default:
break;
}
}
//pwm freq and duty cycle config
void lega_pwm_cfg(lega_pwm_dev_t *pwm)
{
uint32_t tmp_value;
switch(pwm->port)
{
case PWM_OUTPUT_CH0:
PWM->PWMCTL |= PWM_COUNT_MODE; //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM01LOAD & (~(0x0000FFFF));
tmp_value |= (SYSTEM_CLOCK / pwm->config.freq - 1);
PWM->PWM01LOAD = tmp_value;
tmp_value = PWM->PWM0CMP & (~(0x0000FFFF));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle));
PWM->PWM0CMP = tmp_value;
PWM->PWM01DB = 0;
break;
case PWM_OUTPUT_CH1:
PWM->PWMCTL |= PWM_COUNT_MODE; //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM01LOAD & (~(0x0000FFFF));
tmp_value |= (SYSTEM_CLOCK / pwm->config.freq - 1);
PWM->PWM01LOAD = tmp_value;
tmp_value = PWM->PWM0CMP & (~(0xFFFF0000));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle)) << 16;
PWM->PWM0CMP = tmp_value;
PWM->PWM01DB = 0;
break;
case PWM_OUTPUT_CH2:
PWM->PWMCTL |= (PWM_COUNT_MODE << 1); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM01LOAD & (~(0xFFFF0000));
tmp_value |= ((uint16_t)(SYSTEM_CLOCK / pwm->config.freq - 1) << 16);
PWM->PWM01LOAD = tmp_value;
tmp_value = PWM->PWM1CMP & (~(0x0000FFFF));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle));
PWM->PWM1CMP = tmp_value;
PWM->PWM01DB = 0;
break;
case PWM_OUTPUT_CH3:
PWM->PWMCTL |= (PWM_COUNT_MODE << 1); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM01LOAD & (~(0xFFFF0000));
tmp_value |= ((uint16_t)(SYSTEM_CLOCK / pwm->config.freq - 1) << 16);
PWM->PWM01LOAD = tmp_value;
tmp_value = PWM->PWM1CMP & (~(0xFFFF0000));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle)) << 16;
PWM->PWM1CMP = tmp_value;
PWM->PWM01DB = 0;
break;
case PWM_OUTPUT_CH4:
PWM->PWMCTL |= (PWM_COUNT_MODE << 2); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM23LOAD & (~(0x0000FFFF));
tmp_value |= (SYSTEM_CLOCK / pwm->config.freq - 1);
PWM->PWM23LOAD = tmp_value;
tmp_value = PWM->PWM2CMP & (~(0x0000FFFF));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle));
PWM->PWM2CMP = tmp_value;
PWM->PWM23DB = 0;
break;
case PWM_OUTPUT_CH5:
PWM->PWMCTL |= (PWM_COUNT_MODE << 2); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM23LOAD & (~(0x0000FFFF));
tmp_value |= (SYSTEM_CLOCK / pwm->config.freq - 1);
PWM->PWM23LOAD = tmp_value;
tmp_value = PWM->PWM2CMP & (~(0xFFFF0000));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle)) << 16;
PWM->PWM2CMP = tmp_value;
PWM->PWM23DB = 0;
break;
case PWM_OUTPUT_CH6:
PWM->PWMCTL |= (PWM_COUNT_MODE << 3); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM23LOAD & (~(0xFFFF0000));
tmp_value |= ((uint16_t)(SYSTEM_CLOCK / pwm->config.freq - 1) << 16);
PWM->PWM23LOAD = tmp_value;
tmp_value = PWM->PWM3CMP & (~(0x0000FFFF));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle));
PWM->PWM3CMP = tmp_value;
PWM->PWM23DB = 0;
break;
case PWM_OUTPUT_CH7:
PWM->PWMCTL |= (PWM_COUNT_MODE << 3); //0: count-up mode, 1: count-up/down mode
tmp_value = PWM->PWM23LOAD & (~(0xFFFF0000));
tmp_value |= ((uint16_t)(SYSTEM_CLOCK / pwm->config.freq - 1) << 16);
PWM->PWM23LOAD = tmp_value;
tmp_value = PWM->PWM3CMP & (~(0xFFFF0000));
tmp_value |= (uint16_t)(SYSTEM_CLOCK / pwm->config.freq * (1-pwm->config.duty_cycle)) << 16;
PWM->PWM3CMP = tmp_value;
PWM->PWM23DB = 0;
break;
default:
break;
}
}
/**
* Initialises a PWM pin
*
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_init(lega_pwm_dev_t *pwm)
{
uint32_t reg_value;
if(NULL == pwm)
{
return -1;
}
if(pwm->port >= LEGA_PWM_CH_NUM)
{
return -1;
}
//pinmux
lega_pwm_pinmux_init(pwm);
//pwm clock enable
reg_value = REG_RD(PERI_CLK_CFG);
REG_WR(PERI_CLK_CFG, (reg_value|PWM_CLK_EN));
PWM->PWMCFG &= ~(1 << pwm->port);
#ifdef HIGHFREQ_MCU160_SUPPORT
PWM->PWMCFG |= (CNT_CLK_DIV_EN | CLK_DIV_CFG);
pwm->config.freq = pwm->config.freq *(1<<((CLK_DIV_CFG>>24)+1));
#endif
lega_pwm_cfg(pwm);
PWM->PWMINVERTTRIG = 0; //invert control
return 0;
}
/**
* Starts Pulse-Width Modulation signal output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_start(lega_pwm_dev_t *pwm)
{
if(NULL == pwm)
{
return -1;
}
if(pwm->port >= LEGA_PWM_CH_NUM)
{
return -1;
}
PWM->PWMCFG |= (1 << pwm->port);
return 0;
}
/**
* Stops output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_stop(lega_pwm_dev_t *pwm)
{
if(NULL == pwm)
{
return -1;
}
if(pwm->port >= LEGA_PWM_CH_NUM)
{
return -1;
}
PWM->PWMCFG &= ~(1 << pwm->port);
return 0;
}
/**
* change the para of pwm
*
* @param[in] pwm the PWM device
* @param[in] para the para of pwm
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_para_chg(lega_pwm_dev_t *pwm, lega_pwm_config_t para)
{
if(NULL == pwm)
{
return -1;
}
if(pwm->port >= LEGA_PWM_CH_NUM)
{
return -1;
}
//lega_pwm_stop(pwm);
pwm->config = para;
lega_pwm_cfg(pwm);
//lega_pwm_start(pwm);
return 0;
}
/**
* De-initialises an PWM interface, Turns off an PWM hardware interface
*
* @param[in] pwm the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_pwm_finalize(lega_pwm_dev_t *pwm)
{
//pwm clock disable
//uint32_t reg_value;
if(NULL == pwm)
{
return -1;
}
if(pwm->port >= LEGA_PWM_CH_NUM)
{
return -1;
}
//one clk enable for 8 pwm channel
//reg_value = REG_RD(PERI_CLK_CFG);
//REG_WR(PERI_CLK_CFG, (reg_value&(~PWM_CLK_EN)));
return lega_pwm_stop(pwm);
}

View file

@ -0,0 +1,55 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "sns_silib.h"
#include "crys_rnd.h"
#include "lega_rnd.h"
int lega_rnd_init(lega_rnd_dev_t *rnd)
{
if(NULL == rnd->p_workspace)
{
return -1;
}
//C310 clock enable
#ifdef LEGA_A0V2
REG_WR(SYS_REG_BASE_C310_CLK, 0x1);
delay(50);
#endif
return SaSi_LibInit((CRYS_RND_Context_t *)rnd->p_workspace, (CRYS_RND_WorkBuff_t *)(rnd->p_workspace + sizeof(CRYS_RND_Context_t)));
}
int lega_rnd_generate(lega_rnd_dev_t *rnd)
{
int ret;
if(NULL == rnd->rnd_data || 0 == rnd->rnd_size)
{
return -1;
}
if(NULL != rnd->seed && 0 != rnd->seed_size)
{
/*Set additional input for RND seed*/
ret = CRYS_RND_AddAdditionalInput((CRYS_RND_Context_t *)rnd->p_workspace, rnd->seed, rnd->seed_size);
if(SA_SILIB_RET_OK != ret)
{
return ret;
}
/*Perform instantiation for new seed*/
ret = CRYS_RND_Instantiation((CRYS_RND_Context_t *)rnd->p_workspace, (CRYS_RND_WorkBuff_t *)(rnd->p_workspace + sizeof(CRYS_RND_Context_t)));
if(SA_SILIB_RET_OK != ret)
{
return ret;
}
}
/*Try to create two vectors and check that the vectors are different*/
return CRYS_RND_GenerateVector(&((CRYS_RND_Context_t *)rnd->p_workspace)->rndState, rnd->rnd_size, rnd->rnd_data);
}
int lega_rnd_finalize(lega_rnd_dev_t *rnd)
{
return SaSi_LibFini((CRYS_RND_Context_t *)rnd->p_workspace);
}

View file

@ -0,0 +1,185 @@
#include <stdio.h>
#include <time.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_rtc.h"
lega_rtc_time_t *p_lega_rtc_time = (lega_rtc_time_t *)(RTC_TIME_RETENTION_RAM_ADDR);
void SLEEP_IRQHandler(void)
{
lega_intrpt_enter();
struct tm tm1;
struct tm *p_tm1;
time_t time1;
//RTC int sts check and clear
if(REG_RD(LEGA_IRQ_STS_REG_ADDR) & (1 << SLEEP_IRQn))
{
//clear irq
RTC->CTRL &= ~RTC_INT_ENABLE;
tm1.tm_year = p_lega_rtc_time->year;
tm1.tm_mon = p_lega_rtc_time->month;
tm1.tm_mday = p_lega_rtc_time->date;
tm1.tm_hour = p_lega_rtc_time->hr;
tm1.tm_min = p_lega_rtc_time->min;
tm1.tm_sec = p_lega_rtc_time->sec;
time1 = RTC_MAX_DAY * SECOND_PER_DAY - 1;
time1 += mktime(&tm1);
p_tm1 = gmtime(&time1);
p_lega_rtc_time->year = p_tm1->tm_year;
p_lega_rtc_time->month = p_tm1->tm_mon;
p_lega_rtc_time->date = p_tm1->tm_mday;
p_lega_rtc_time->hr = p_tm1->tm_hour;
p_lega_rtc_time->min = p_tm1->tm_min;
p_lega_rtc_time->sec = p_tm1->tm_sec;
p_lega_rtc_time->weekday = p_tm1->tm_wday;
while(REG_RD(LEGA_IRQ_STS_REG_ADDR) & (1 << SLEEP_IRQn));
//enable int
RTC->CTRL |= RTC_INT_ENABLE;
}
lega_intrpt_exit();
}
/**
* This function will initialize the on board CPU real time clock
*
*
* @param[in] rtc rtc device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_init(lega_rtc_dev_t *rtc)
{
if(NULL == rtc)
{
return -1;
}
if(0 == rtc->port)
{
if(!(RTC->CTRL & RTC_ENABLE)) //for deep sleep wake up reboot case consider
{
p_lega_rtc_time->year = RTC_INIT_YEAR;
p_lega_rtc_time->month = RTC_INIT_MONTH;
p_lega_rtc_time->date = RTC_INIT_DATE;
p_lega_rtc_time->hr = RTC_INIT_HOUR;
p_lega_rtc_time->min = RTC_INIT_MINUTE;
p_lega_rtc_time->sec = RTC_INIT_SECOND;
p_lega_rtc_time->weekday = RTC_INIT_WEEKDAY;
RTC->CTRL &= ~RTC_ENABLE;
RTC->CNT_TICK = RTC_TICK_CNT;
RTC->CNT_DATE = (RTC_REFRESH_DAY << 17 | RTC_REFRESH_HOUR << 12 | RTC_REFRESH_MINUTE << 6 | RTC_REFRESH_SECOND);
RTC->CTRL |= RTC_CNT_CYCLE_ENABLE | RTC_INT_ENABLE | RTC_ENABLE; //sel internal RC clock, calibration needed
//RTC->CTRL |= RTC_CNT_CYCLE_ENABLE | RTC_INT_ENABLE | RTC_ENABLE | CLK32K_SEL | SW_OVERRIDE_REG_POR; //sel ext 32.768k XTAL
NVIC_EnableIRQ(SLEEP_IRQn);
}
return 0;
}
return -1;
}
/**
* This function will return the value of time read from the on board CPU real time clock.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_get_time(lega_rtc_dev_t *rtc, lega_rtc_time_t *time)
{
struct tm tm1;
struct tm *p_tm1;
time_t time1;
if((NULL == rtc) || (NULL == time))
{
return -1;
}
if(0 == rtc->port)
{
time1 = GET_RTC_CURRENT_DATE();
time1 = (((time1 >> 17) & 0xFF) * 86400 + ((time1 >> 12) & 0x1F) * 3600 + ((time1 >> 6) & 0x3F) * 60 + (time1 & 0x3F));
tm1.tm_year = p_lega_rtc_time->year;
tm1.tm_mon = p_lega_rtc_time->month;
tm1.tm_mday = p_lega_rtc_time->date;
tm1.tm_hour = p_lega_rtc_time->hr;
tm1.tm_min = p_lega_rtc_time->min;
tm1.tm_sec = p_lega_rtc_time->sec;
time1 += mktime(&tm1);
p_tm1 = gmtime(&time1);
time->year = p_tm1->tm_year;
time->month = p_tm1->tm_mon;
time->date = p_tm1->tm_mday;
time->hr = p_tm1->tm_hour;
time->min = p_tm1->tm_min;
time->sec = p_tm1->tm_sec;
time->weekday = p_tm1->tm_wday;
return 0;
}
return -1;
}
/**
* This function will set MCU RTC time to a new value.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_set_time(lega_rtc_dev_t *rtc, const lega_rtc_time_t *time)
{
if((NULL == rtc) || (NULL == time))
{
return -1;
}
if(0 == rtc->port)
{
RTC->CTRL &= ~RTC_ENABLE;
delay(200);
RTC->CTRL |= RTC_ENABLE;
*p_lega_rtc_time = *time;
return 0;
}
return -1;
}
/**
* De-initialises an RTC interface, Turns off an RTC hardware interface
*
* @param[in] RTC the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_rtc_finalize(lega_rtc_dev_t *rtc)
{
if(NULL == rtc)
{
return -1;
}
if(0 == rtc->port)
{
NVIC_DisableIRQ(SLEEP_IRQn);
RTC->CTRL &= ~(RTC_ENABLE | RTC_INT_ENABLE | RTC_CNT_CYCLE_ENABLE);
RTC->CNT_TICK = 0;
RTC->CNT_DATE = 0;
return 0;
}
return -1;
}

View file

@ -0,0 +1,538 @@
#include <stdio.h>
#include <time.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_spi.h"
lega_spi_trans_mode_t spi_trans_mode = SPI_TRANS_PIO_MODE;
//lega_spi_trans_mode_t spi_trans_mode = SPI_TRANS_DMA_MODE;
//default settings for different spi ports
lega_spi_controller_t spi_cntls[3] = {
{
.name = "spi0",//master only
.left_tx_size = 0,
.left_rx_size = 0,
.pvtx = NULL,
.pvrx = NULL,
.tx_func = tx_8bit,
.rx_func = rx_8bit,
.bits = 8,
.lsb = 0,//only msb
.is_loopback = 0,
},
{
.name = "spi1",//master only
.left_tx_size = 0,
.left_rx_size = 0,
.pvtx = NULL,
.pvrx = NULL,
.tx_func = tx_8bit,
.rx_func = rx_8bit,
.bits = 8,
.lsb = 0,//only msb
.is_loopback = 0,
},
{
.name = "spi2",//slave only
.left_tx_size = 0,
.left_rx_size = 0,
.pvtx = NULL,
.pvrx = NULL,
.tx_func = tx_8bit,
.rx_func = rx_8bit,
.bits = 8,
.lsb = 0,//only msb
.is_loopback = 0,
},
};
void tx_8bit(int port)
{
uint8_t *tx_data;
tx_data = (uint8_t *)spi_cntls[port].pvtx;
if (tx_data) {
REG_WR(SPIx_DR(port, 0), *tx_data++);
spi_cntls[port].pvtx = tx_data;
}
spi_cntls[port].left_tx_size--;
}
void rx_8bit(int port)
{
uint8_t *rx_data;
rx_data = (uint8_t *)spi_cntls[port].pvrx;
if (rx_data) {
*rx_data++ = REG_RD(SPIx_DR(port, 0));
spi_cntls[port].pvrx = rx_data;
}
spi_cntls[port].left_rx_size--;
}
void tx_16bit(int port)
{
uint16_t *tx_data;
tx_data = (uint16_t *)spi_cntls[port].pvtx;
if (tx_data) {
REG_WR(SPIx_DR(port, 0), *tx_data++);
spi_cntls[port].pvtx = tx_data;
}
spi_cntls[port].left_tx_size--;
}
void rx_16bit(int port)
{
uint16_t *rx_data;
rx_data = (uint16_t *)spi_cntls[port].pvrx;
if (rx_data) {
*rx_data++ = REG_RD(SPIx_DR(port, 0));
spi_cntls[port].pvrx = rx_data;
}
spi_cntls[port].left_rx_size--;
}
void tx_32bit(int port)
{
uint32_t *tx_data;
tx_data = (uint32_t *)spi_cntls[port].pvtx;
if (tx_data) {
REG_WR(SPIx_DR(port, 0), *tx_data++);
spi_cntls[port].pvtx = tx_data;
}
spi_cntls[port].left_tx_size--;
}
void rx_32bit(int port)
{
uint32_t *rx_data;
rx_data = (uint32_t *)spi_cntls[port].pvrx;
if (rx_data) {
*rx_data++ = REG_RD(SPIx_DR(port, 0));
spi_cntls[port].pvrx = rx_data;
}
spi_cntls[port].left_rx_size--;
}
/*
spi_enable: enable/disable spi controller
@port: spi port index
@enable: 1 -- enable spi controller
0 -- disable spi controller
*/
int spi_enable(int port, int enable)
{
if (port < 0 || port > 2)
return -1;
if (enable)
REG_WR(SPIx_SSIEN(port), SPI_EN);
else
REG_WR(SPIx_SSIEN(port), SPI_DISABLE);
return 0;
}
/*
spi_pio_trans_data using PIO mode to transfer and receive data
*/
int spi_pio_trans_data(int port)
{
REG_WR(SPIx_IM(port), REG_RD(SPIx_IM(port)) | SPI_IS_TX_EMPTY | SPI_IS_RX_FULL);
spi_enable(port, 1);
while (!(!(REG_RD(SPIx_ST(port)) & SPI_ST_BUSY) && spi_cntls[port].left_tx_size == 0 && spi_cntls[port].left_rx_size == 0))
;
return 1;
}
volatile int is_tx_dma_done = 0;
volatile int is_rx_dma_done = 0;
void DMA_CTRL_IRQHandler(void)
{
if (DMA_STATUSBLOCK & 0x1) {
DMA_CLEARBLOCK = 0x1;
is_tx_dma_done = 1;
}
if (DMA_STATUSBLOCK & 0x2) {
DMA_CLEARBLOCK = 0x2;
is_rx_dma_done = 1;
}
}
/**
* spi_dma_trans_data using DMA mode to transfer and receive data
*
* @param[in] spi port index
*/
int spi_dma_trans_data(int port)
{
int dma_chan_en_reg;
REG_WR(SPIx_IM(port), 0x0);
is_tx_dma_done = is_rx_dma_done = 0;
dma_chan_en_reg = CHENREG_L;
spi_enable(port, 1);
//check if there is DMA channel resource
if (dma_chan_en_reg)
return -1;
//spi slave
if (port == 2) {
spi_cntls[port].tx_func(port);
spi_cntls[port].tx_func(port);
spi_cntls[port].tx_func(port);
spi_cntls[port].tx_func(port);
}
DMA_SAR0_L = (int)(spi_cntls[port].pvtx);//spi tx data<--from mem
DMA_DAR0_L = SPIx_DR(port, 0);
DMA_SAR1_L = SPIx_DR(port, 0);//spi rx data-->mem
DMA_DAR1_L = (int)(spi_cntls[port].pvrx);
DMA_LLP0_L = 0x00;
DMA_LLP0_H = 0x00;
DMA_LLP1_L = 0x00;
DMA_LLP1_H = 0x00;
switch (spi_cntls[port].bits) {
case 8:
DMA_CTL0_L = 0x02104101;
DMA_CTL0_H = spi_cntls[port].left_tx_size;
DMA_CTL1_L = 0x00A01401;
DMA_CTL1_H = spi_cntls[port].left_rx_size;
break;
case 16:
DMA_CTL0_L = 0x02104113;
DMA_CTL0_H = spi_cntls[port].left_tx_size;
DMA_CTL1_L = 0x00A01413;
DMA_CTL1_H = spi_cntls[port].left_rx_size;
break;
case 32:
DMA_CTL0_L = 0x02104125;
DMA_CTL0_H = spi_cntls[port].left_tx_size;
DMA_CTL1_L = 0x00A01425;
DMA_CTL1_H = spi_cntls[port].left_rx_size;
break;
}
if (port == 0) {
DMA_CFG0_L = 0x00000000; //31, reload DST, 19,18, interface polarity active high, 11=1 src software,10=0 dest hardware,
DMA_CFG0_H = 0x00003302; //[11],dest ch0 [7],src ch0 [1],enable fifo mode
DMA_CFG1_L = 0x00000000; //30, reload SRC, 19,18, interface polarity active high, 11=1 src software,10=0 dest hardware,
DMA_CFG1_H = 0x00003B82; //[11],dest ch1 [7],src ch1 [1],enable fifo mode
} else if (port == 1) {
DMA_CFG0_L = 0x00000000;
DMA_CFG0_H = 0x00004402;
DMA_CFG1_L = 0x00000000;
DMA_CFG1_H = 0x00004C82;
} else if (port == 2) {
DMA_CFG0_L = 0x00000000; //31, reload DST, 19,18, interface polarity active high, 11=1 src software,10=0 dest hardware,
DMA_CFG0_H = 0x00005502; //[14:11]=10,dest ch0. [10:7]=10,src ch0. enable fifo mode
DMA_CFG1_L = 0x00000000; //30, reload SRC, 19,18, interface polarity active high, 11=1 src software,10=0 dest hardware,
DMA_CFG1_H = 0x00005D82; //[14:11]=11,dest ch0. [10:7]=11,src ch0. enable fifo mode
}
DMA_MASKBLOCK = 0x0303;
DMACFGREG_L = 0x1;
CHENREG_L = 0x0303;
//wait until tx/rx done
while ((is_tx_dma_done == 0 || is_rx_dma_done == 0))
;
spi_cntls[port].left_tx_size = 0;
spi_cntls[port].left_rx_size = 0;
CHENREG_L = 0x0000;
return 1;
}
/**
* SPI interrupt handler
*
* @param[in] spi port index
*/
void spi_isr(int port)
{
uint32_t int_st, st, tx_level;
int_st = REG_RD(SPIx_IS(port));
if (int_st & (SPI_IS_RX_OF | SPI_IS_RX_UF | SPI_IS_TX_OF)) {
REG_RD(SPIx_RXOIC(port));
REG_RD(SPIx_RXUIC(port));
REG_RD(SPIx_TXOIC(port));
return;
}
if (int_st & SPI_IS_TX_EMPTY) {
tx_level = REG_RD(SPIx_TXFL(port));
//optimization here for transfer multi bytes continuesly: change from if -> while
//spi2 as slave, spi0/spi1 as master
if (port == 2) {
while (spi_cntls[port].left_tx_size > 0 && ((tx_level & SPI_TXFL_MASK) != SPI_TXFL_MASK)) {
spi_cntls[port].tx_func(port);
tx_level = REG_RD(SPIx_TXFL(port));
}
} else {
if (spi_cntls[port].left_tx_size > 0 && ((tx_level & SPI_TXFL_MASK) != SPI_TXFL_MASK)) {
spi_cntls[port].tx_func(port);
tx_level = REG_RD(SPIx_TXFL(port));
}
}
if (0 == spi_cntls[port].left_tx_size)
REG_WR(SPIx_IM(port), REG_RD(SPIx_IM(port)) & ~(SPI_IS_TX_EMPTY) );
}
int_st = REG_RD(SPIx_IS(port));
if (int_st & SPI_IS_RX_FULL) {//rx full
// receive at rx fifo
st = REG_RD(SPIx_ST(port));
while (spi_cntls[port].left_rx_size > 0 && (st & SPI_ST_RFNE)) {
spi_cntls[port].rx_func(port);
st = REG_RD(SPIx_ST(port));
}
if (0 == spi_cntls[port].left_rx_size)
REG_WR(SPIx_IM(port), REG_RD(SPIx_IM(port)) & ~(SPI_ST_RFF) );
}
return;
}
void SPI0_IRQHandler(void)
{
spi_isr(0);
}
void SPI1_IRQHandler(void)
{
spi_isr(1);
}
void SPI2_IRQHandler(void)
{
spi_isr(2);
}
/**
* Initialises the SPI interface for a given SPI device
*
* @param[in] spi the spi device
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_init(lega_spi_dev_t *spi)
{
uint8_t cpol, cpha;
if (spi->port > 2 || spi->port < 0)
return -1;
REG_WR(0x40000830, REG_RD(0x40000830) | 0x7);
switch (spi->port) {
case 0:
#if defined(LEGA_A0V1)
REG_WR(0x40000038, REG_RD(0x40000038) | 0x11000000);
REG_WR(0x4000003c, REG_RD(0x4000003c) | 0x00000011);
#else
REG_WR(0x40000004, REG_RD(0x40000004) | 0x11000000);
REG_WR(0x40000008, REG_RD(0x40000008) | 0x00000011);
#endif
NVIC_SetPriority(SPI0_IRQn, 5);
NVIC_EnableIRQ(SPI0_IRQn);
break;
case 1:
#if defined(LEGA_A0V1)
REG_WR(0x40000038, REG_RD(0x40000038) | 0x00003333);
#else
REG_WR(0x40000004, REG_RD(0x40000004) | 0x00003333);
#endif
NVIC_SetPriority(SPI1_IRQn, 2);
NVIC_EnableIRQ(SPI1_IRQn);
break;
case 2:
#if defined(LEGA_A0V1)
REG_WR(0x4000003c, REG_RD(0x4000003c) | 0x22220000);
#else
REG_WR(0x40000008, REG_RD(0x40000008) | 0x22220000);
#endif
NVIC_SetPriority(SPI2_IRQn, 5);
NVIC_EnableIRQ(SPI2_IRQn);
break;
default:
break;
}
spi_enable(spi->port, 0);
switch (spi->config.mode) {
case 0:
cpol = 0;
cpha = 0;
break;
case 1:
cpol = 0;
cpha = 1;
break;
case 2:
cpol = 1;
cpha = 0;
break;
case 3:
cpol = 1;
cpha = 1;
break;
default:
cpol = 0;
cpha = 0;
break;
}
switch (spi_cntls[spi->port].bits) {
case 8:
spi_cntls[spi->port].tx_func = tx_8bit;
spi_cntls[spi->port].rx_func = rx_8bit;
break;
case 16:
spi_cntls[spi->port].tx_func = tx_16bit;
spi_cntls[spi->port].rx_func = rx_16bit;
break;
case 32:
spi_cntls[spi->port].tx_func = tx_32bit;
spi_cntls[spi->port].rx_func = rx_32bit;
break;
}
REG_WR(SPIx_CTRL0(spi->port), ((spi_cntls[spi->port].bits - 1) << SPI_DFS32_SHIFT) | (0 << SPI_TMOD_SHIFT) | (spi_cntls[spi->port].is_loopback << SPI_SRL_SHIFT ) | (cpha << SPI_CPHA_SHIFT) | (cpol << SPI_CPOL_SHIFT) | (0 << SPI_FR_SHIFT));
REG_WR(SPIx_TXFTL(spi->port), 0x0 & SPI_TFT_MASK);//32/4
REG_WR(SPIx_RXFTL(spi->port), 0x0 & SPI_RFT_MASK);//32/4
REG_WR(SPIx_BAUD(spi->port), (SYSTEM_CLOCK/spi->config.freq) & SPI_BAUD_MASK);
if (spi->port != 2)
REG_WR(SPIx_SE(spi->port), 0x1);
REG_WR(SPIx_IM(spi->port), 0x0);
spi->priv = (void *)&spi_cntls[spi->port];
spi_enable(spi->port, 0);
if (spi_trans_mode == 1) {
REG_WR(SPIx_DMAC(spi->port), 0x3);
//ensure using dma the transfer size is 4x size
REG_WR(SPIx_DMATDL(spi->port), 0x0);
REG_WR(SPIx_DMARDL(spi->port), 0x0);
REG_WR(0x40000950, REG_RD(0x40000950) | 0x800);
REG_WR(0x40000944, REG_RD(0x40000944) | 0x80);
NVIC_SetPriority(DMA_CTRL_IRQn, 2);
NVIC_EnableIRQ(DMA_CTRL_IRQn);
} else {
REG_WR(SPIx_DMAC(spi->port), 0x0);
REG_WR(SPIx_DMATDL(spi->port), 0x0);
REG_WR(SPIx_DMARDL(spi->port), 0x0);
}
return 0;
}
/**
* Spi send
*
* @param[in] spi the spi device
* @param[in] data spi send data
* @param[in] size spi send data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_send(lega_spi_dev_t *spi, const uint8_t *data, uint16_t size, uint32_t timeout)
{
int32_t ret;
lega_spi_controller_t *spi_cntl;
spi_cntl = (lega_spi_controller_t *)spi->priv;
spi_cntl->left_tx_size = size;
spi_cntl->left_rx_size = size;
spi_cntl->pvtx = (void *)data;
spi_cntl->pvrx = NULL;
if (spi_trans_mode == SPI_TRANS_PIO_MODE)//pio way
ret = spi_pio_trans_data(spi->port);
else//dma way
ret = spi_dma_trans_data(spi->port);
return ret;
}
/**
* spi_recv
*
* @param[in] spi the spi device
* @param[out] data spi recv data
* @param[in] size spi recv data size
* @param[in] timeout timeout in ms
*
* @return 0 : on success, EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_recv(lega_spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout)
{
int32_t ret;
lega_spi_controller_t *spi_cntl;
spi_cntl = spi->priv;
spi_cntl->left_tx_size = size;
spi_cntl->left_rx_size = size;
spi_cntl->pvtx = NULL;
spi_cntl->pvrx = data;
if (spi_trans_mode == SPI_TRANS_PIO_MODE)//pio way
ret = spi_pio_trans_data(spi->port);
else//dma way
ret = spi_dma_trans_data(spi->port);
return ret;
}
/**
* spi send data and recv
*
* @param[in] spi the spi device
* @param[in] tx_data spi send data
* @param[in] rx_data spi recv data
* @param[in] size spi data to be sent and recived
* @param[in] timeout timeout in ms
*
* @return 0, on success; EIO : if the SPI device could not be initialised
*/
int32_t lega_spi_send_recv(lega_spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data,
uint16_t size, uint32_t timeout)
{
int32_t ret;
lega_spi_controller_t *spi_cntl;
spi_cntl = spi->priv;
spi_cntl->left_tx_size = size;
spi_cntl->left_rx_size = size;
spi_cntl->pvtx = tx_data;
spi_cntl->pvrx = rx_data;
if (spi_trans_mode == SPI_TRANS_PIO_MODE)//pio way
ret = spi_pio_trans_data(spi->port);
else//dma way
ret = spi_dma_trans_data(spi->port);
return ret;
}
/**
* De-initialises a SPI interface
*
*
* @param[in] spi the SPI device to be de-initialised
*
* @return 0 : on success, EIO : if an error occurred
*/
int32_t lega_spi_finalize(lega_spi_dev_t *spi)
{
int port;
port = spi->port;
if (port < 0 || port > 2)
return -1;
REG_WR(SPIx_IM(port), ~SPI_IS_MSK);
spi_enable(port, 0);
switch (port) {
case 0:
NVIC_DisableIRQ(SPI0_IRQn);
break;
case 1:
NVIC_DisableIRQ(SPI1_IRQn);
break;
case 2:
NVIC_DisableIRQ(SPI2_IRQn);
break;
default:
break;
}
return 0;
}

View file

@ -0,0 +1,161 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_timer.h"
lega_timer_cb_t g_lega_timer_handler[LEGA_TIMER_NUM];
void TIMER_IRQHandler(void)
{
lega_intrpt_enter();
if(TIMER1->MIS)
{
TIMER1->INTCLR = 1; //clear irq
if(g_lega_timer_handler[LEGA_TIMER1_INDEX].cb)
{
g_lega_timer_handler[LEGA_TIMER1_INDEX].cb(g_lega_timer_handler[LEGA_TIMER1_INDEX].arg);
}
}
if(TIMER2->MIS)
{
TIMER2->INTCLR = 1; //clear irq
if(g_lega_timer_handler[LEGA_TIMER2_INDEX].cb)
{
g_lega_timer_handler[LEGA_TIMER2_INDEX].cb(g_lega_timer_handler[LEGA_TIMER2_INDEX].arg);
}
}
lega_intrpt_exit();
}
/**
* init a hardware timer
*
* @param[in] tmr timer struct
* @param[in] period micro seconds for repeat timer trigger
* @param[in] auto_reoad set to 0, if you just need oneshot timer
* @param[in] cb callback to be triggered after useconds
* @param[in] ch timer channel
* @param[in] arg passed to cb
*/
int32_t lega_timer_init(lega_timer_dev_t *tim)
{
uint8_t timer_mode;
uint32_t reg_value;
if(NULL == tim)
{
return -1;
}
if(tim->port >= LEGA_TIMER_NUM)
{
return -1;
}
// Set Timer Clock Enable
reg_value = REG_RD(PERI_CLK_CFG);
REG_WR(PERI_CLK_CFG, (reg_value|TIMER_SCLK_EN));
if(TIMER_RELOAD_AUTO == tim->config.reload_mode)
{
timer_mode = PERIODIC_MODE;
}
else if(TIMER_RELOAD_MANU == tim->config.reload_mode)
{
timer_mode = ONE_SHOT_MODE;
}
else
{
return -1;
}
g_lega_timer_handler[tim->port].cb = tim->config.cb;
g_lega_timer_handler[tim->port].arg = tim->config.arg;
if(LEGA_TIMER1_INDEX == tim->port)
{
TIMER1->CONTROL = TIMER_DISABLE; //disable timer first
TIMER1->LOAD = tim->config.period * (SYSTEM_CLOCK / 1000000); //1000000 for us
TIMER1->CONTROL |= (TIMER_PRESCALE | TIMER_SIZE | timer_mode); //timer control
}
else //if(LEGA_TIMER2_INDEX == tim->port)
{
TIMER2->CONTROL = TIMER_DISABLE; //disable timer first
TIMER2->LOAD = tim->config.period * (SYSTEM_CLOCK / 1000000); //1000000 for us
TIMER2->CONTROL |= (TIMER_PRESCALE | TIMER_SIZE | timer_mode); //timer control
}
return 0;
}
/**
* start a hardware timer
*
* @return 0 == success, EIO == failure
*/
int32_t lega_timer_start(lega_timer_dev_t *tim)
{
if(NULL == tim)
{
return -1;
}
if(LEGA_TIMER1_INDEX == tim->port)
{
TIMER1->CONTROL |= (TIMER_ENABLE | INTERRUPT_EN); //timer control
}
else if(LEGA_TIMER2_INDEX == tim->port)
{
TIMER2->CONTROL |= (TIMER_ENABLE | INTERRUPT_EN); //timer control
}
else
{
return -1;
}
NVIC_EnableIRQ(TIMER_IRQn); //0x20
return 0;
}
/**
* stop a hardware timer
*
* @param[in] tmr timer struct
* @param[in] cb callback to be triggered after useconds
* @param[in] arg passed to cb
*/
void lega_timer_stop(lega_timer_dev_t *tim)
{
if(NULL == tim)
{
return;
}
if(LEGA_TIMER1_INDEX == tim->port)
{
TIMER1->CONTROL = TIMER_DISABLE; //timer control
}
else if(LEGA_TIMER2_INDEX == tim->port)
{
TIMER2->CONTROL = TIMER_DISABLE; //timer control
}
else
{
return;
}
//two timers use same IRQ
//NVIC_DisableIRQ(TIMER_IRQn);
g_lega_timer_handler[tim->port].cb = NULL;
g_lega_timer_handler[tim->port].arg = NULL;
}
/**
* De-initialises an TIMER interface, Turns off an TIMER hardware interface
*
* @param[in] timer the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_timer_finalize(lega_timer_dev_t *tim)
{
//uint32_t reg_value;
lega_timer_stop(tim);
// Set Timer Clock Disable
//one clk enable for 2 timer
//reg_value = REG_RD(PERI_CLK_CFG);
//REG_WR(PERI_CLK_CFG, (reg_value&(~TIMER_SCLK_EN)));
return 0;
}

View file

@ -0,0 +1,431 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "system_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_uart.h"
lega_uart_callback_func g_lega_uart_callback_handler[LEGA_UART_NUM];
void UART_SendData(UART_TypeDef* UARTx, unsigned char Data)
{
UARTx->THR = Data;
while((UARTx->LSR & (DW_UART_LSR_TX_THRE|DW_UART_LSR_TX_TEMT)) != DW_UART_TX_TC);
}
uint8_t UART_ReceiveData(UART_TypeDef* UARTx)
{
while((UARTx->LSR & DW_UART_LSR_DR) == RESET);
return UARTx->RBR;
}
ITStatus UART_Get_Data_Ready_Status(UART_TypeDef* UARTx, unsigned int UART_DATA_READY)
{
ITStatus bitstatus = RESET;
if(((UARTx->LSR) & UART_DATA_READY) != (uint16_t)RESET)
bitstatus=SET;
else
bitstatus=RESET;
return bitstatus;
}
void UART_IRQHandler(UART_TypeDef * uart)
{
uint8_t res;
char ch;
uint8_t uart_port;
if(UART0 == uart)
{
uart_port = LEGA_UART0_INDEX;
}
else if(UART1 == uart)
{
uart_port = LEGA_UART1_INDEX;
}
else if(UART2 == uart)
{
uart_port = LEGA_UART2_INDEX;
}
else
{
return;
}
while(UART_Get_Data_Ready_Status(uart, DW_UART_LSR_DR) != RESET)
{
res = UART_ReceiveData(uart);
ch = (char)res;
if(g_lega_uart_callback_handler[uart_port])
{
g_lega_uart_callback_handler[uart_port](ch);
}
}
}
void UART0_IRQHandler(void)
{
lega_intrpt_enter();
UART_IRQHandler(UART0);
lega_intrpt_exit();
}
void UART1_IRQHandler(void)
{
lega_intrpt_enter();
UART_IRQHandler(UART1);
lega_intrpt_exit();
}
void UART2_IRQHandler(void)
{
lega_intrpt_enter();
UART_IRQHandler(UART2);
lega_intrpt_exit();
}
static void pin_pullup(uint8_t pin)
{
uint32_t reg_value;
reg_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, reg_value & ~(1 << pin));
reg_value = REG_RD(PAD_PS_REG);
REG_WR(PAD_PS_REG, reg_value | 1 << pin);
reg_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, reg_value | 1 << pin);
}
/**
* Initialises a UART interface
*
*
* @param[in] uart the interface which should be initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_init(lega_uart_dev_t *uart)
{
UART_TypeDef* UARTx;
uint32_t baudrate;
int flow_control;
uint32_t data_width;
int stop_bit;
int parity_flag;
uint32_t dll, tmp_value;
if(NULL == uart)
{
return -1;
}
if(LEGA_UART0_INDEX == uart->port)
{
UARTx = UART0;
}
else if(LEGA_UART1_INDEX == uart->port)
{
UARTx = UART1;
}
else if(LEGA_UART2_INDEX == uart->port)
{
UARTx = UART2;
}
else
{
return -1;
}
if((0 == uart->config.baud_rate)
|| (uart->config.data_width >= DATA_9BIT)
|| (uart->config.parity > PARITY_EVEN)
|| (uart->config.stop_bits > STOP_2BITS)
|| (uart->config.flow_control > FLOW_CTRL_CTS_RTS)
|| (uart->config.mode > TX_RX_MODE))
{
return -1;
}
baudrate = uart->config.baud_rate;
data_width = uart->config.data_width;
stop_bit = uart->config.stop_bits << 2;
if(uart->config.parity == PARITY_NO)
{
parity_flag = uart->config.parity << 3;
}
else
{
parity_flag = ((uart->config.parity-1)<<4) | (1<<3);
}
if(FLOW_CTRL_DISABLED == uart->config.flow_control)
{
flow_control = uart->config.flow_control<<5;
}
else
{
flow_control = 1 << 5;
}
//uart pin mux configure
if(UARTx == UART0)
{
tmp_value = REG_RD(UART0_PIN_MUX_REG) & (~DW_UART0_GPIO_MASK);
REG_WR(UART0_PIN_MUX_REG, (tmp_value | DW_UART0_TX | DW_UART0_RX));//gpio0/gpio1
tmp_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (tmp_value & (~(UART0_PAD_MASK))));
tmp_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (tmp_value & (~(UART0_PAD_MASK))));
pin_pullup(1);
}
else if(UARTx == UART1)
{
tmp_value = REG_RD(UART1_PIN_MUX_REG) & (~DW_UART1_GPIO_MASK);
REG_WR(UART1_PIN_MUX_REG, (tmp_value | DW_UART1_TX | DW_UART1_RX));//gpio2/gpio3
tmp_value = REG_RD(HW_CTRL_PE_PS);
REG_WR(HW_CTRL_PE_PS, (tmp_value & (~(UART1_PAD_MASK))));
tmp_value = REG_RD(PAD_PE_REG);
REG_WR(PAD_PE_REG, (tmp_value & (~(UART1_PAD_MASK))));
pin_pullup(3);
}
else
{
tmp_value = REG_RD(UART2_PIN_MUX_REG) & (~DW_UART2_GPIO_MASK);
REG_WR(UART2_PIN_MUX_REG, (tmp_value | DW_UART2_TX | DW_UART2_RX));//gpio6/gpio7 for a0v1; gpio12/gpio13 for a0v2
}
//uart sclk enable and sclk root clk setting (XTAL)
//fpga no effect, soc need
#ifdef LEGA_A0V1
if(UARTx == UART0)
{
tmp_value = REG_RD(UART_CLK_REG_ADDR);
REG_WR(UART_CLK_REG_ADDR, tmp_value | UART0_SCLK_EN | UART_SCLK_ROOT_SEL_XTAL);
}
else if(UARTx == UART1)
{
tmp_value = REG_RD(UART_CLK_REG_ADDR);
REG_WR(UART_CLK_REG_ADDR, tmp_value | UART1_SCLK_EN | UART_SCLK_ROOT_SEL_XTAL);
}
else
{
tmp_value = REG_RD(UART_CLK_REG_ADDR);
REG_WR(UART_CLK_REG_ADDR, tmp_value | UART2_SCLK_EN | UART_SCLK_ROOT_SEL_XTAL);
}
#else //LEGA_A0V2
if(UARTx==UART0)
{
REG_WR(UART_CLK_REG_ADDR,REG_RD(UART_CLK_REG_ADDR)|UART0_SCLK_EN);
}
else if(UARTx==UART1)
{
REG_WR(UART_CLK_REG_ADDR,REG_RD(UART_CLK_REG_ADDR)|UART1_SCLK_EN);
}
else
{
REG_WR(UART_CLK_REG_ADDR,REG_RD(UART_CLK_REG_ADDR)|UART2_SCLK_EN);
}
#endif
#ifdef LEGA_A0V1
//uart clk rst
if(UARTx == UART1)
{
REG_WR(UART1_CLK_RST_REG_ADDR, (UART1_HCLK_RESET | UART1_SCLK_RESET));
delay(20);
REG_WR(UART1_CLK_RST_REG_ADDR, 0x00);
}
else
{
//SRR soft reset
UARTx->SRR = DW_UART_SRR_UR;
}
#else
//SRR soft reset
UARTx->SRR = DW_UART_SRR_UR;
#endif
//disable all uart interrupt
UARTx->IER=DW_UART_DISABLE_ALL_IRQ;
//check busy
while(UARTx->USR & DW_UART_USR_BUSY);
dll= UART_BASE_CLOCK/(baudrate*16);
dll= ((UART_BASE_CLOCK - dll*(baudrate*16)) < (baudrate*16)/2) ? dll : (dll+1); //minus four , add five
//set latch for dll,set baud
UARTx->LCR |= DW_UART_LCR_DLAB;
//for baudrate=115200, we set it to 1 because hw has done pll divider
UARTx->DLL = dll&0xFF;
UARTx->DLH = (dll>>8)&0xFF;
//clear bit 7 of dll latch
UARTx->LCR &=~(DW_UART_LCR_DLAB);
//set dps
UARTx->LCR &=(~DW_UART_LCR_DPS_MASK);
//bit[0:1]=11 means 8 bits data size and bit[2]=0 means 1 bit stop
UARTx->LCR |= data_width|stop_bit|parity_flag;
UARTx->MCR |= flow_control;
//enable FIFO
UARTx->FCR |= (DW_UART_FCR_FIFO_ENABLE|DW_UART_FCR_FIFO_RCVR_HALF_FULL);
//enable rx interrupt
UARTx->IER = DW_UART_IER_RX_INT_EN;
//enable cm4 interrupt
if(UARTx==UART0)
{
NVIC_EnableIRQ(UART0_IRQn);
}
else if(UARTx==UART1)
{
NVIC_EnableIRQ(UART1_IRQn);
}
else
{
NVIC_EnableIRQ(UART2_IRQn);
}
if(uart->priv)
{
g_lega_uart_callback_handler[uart->port] = (lega_uart_callback_func)(uart->priv);
}
return 0;
}
/**
* Transmit data on a UART interface
*
* @param[in] uart the UART interface
* @param[in] data pointer to the start of data
* @param[in] size number of bytes to transmit
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_send(lega_uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
{
UART_TypeDef* UARTx;
int i = 0;
if((NULL == uart) || (NULL == data))
{
return -1;
}
if(LEGA_UART0_INDEX == uart->port)
{
UARTx = UART0;
}
else if(LEGA_UART1_INDEX == uart->port)
{
UARTx = UART1;
}
else if(LEGA_UART2_INDEX == uart->port)
{
UARTx = UART2;
}
else
{
return -1;
}
for(i = 0; i < size; i++)
{
UART_SendData(UARTx,((uint8_t*)data)[i]);
}
return 0;
}
/**
* Deinitialises a UART interface
*
* @param[in] uart the interface which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_uart_finalize(lega_uart_dev_t *uart)
{
UART_TypeDef* UARTx;
unsigned int tmp_value;
if(NULL == uart)
{
return -1;
}
if(LEGA_UART0_INDEX == uart->port)
{
UARTx = UART0;
}
else if(LEGA_UART1_INDEX == uart->port)
{
UARTx = UART1;
}
else if(LEGA_UART2_INDEX == uart->port)
{
UARTx = UART2;
}
else
{
return -1;
}
//disable all uart interrupt
UARTx->IER = DW_UART_DISABLE_ALL_IRQ;
//disable cm4 interrupt
if(UART0 == UARTx)
{
NVIC_DisableIRQ(UART0_IRQn);
}
else if(UART1 == UARTx)
{
NVIC_DisableIRQ(UART1_IRQn);
}
else
{
NVIC_DisableIRQ(UART2_IRQn);
}
//uart sclk disable, fpga no effect, soc need
if(UART0 == UARTx)
{
REG_WR(UART_CLK_REG_ADDR, REG_RD(UART_CLK_REG_ADDR)&(~UART0_SCLK_EN));
}
else if(UART1 == UARTx)
{
REG_WR(UART_CLK_REG_ADDR, REG_RD(UART_CLK_REG_ADDR)&(~UART1_SCLK_EN));
}
else
{
REG_WR(UART_CLK_REG_ADDR, REG_RD(UART_CLK_REG_ADDR)&(~UART2_SCLK_EN));
}
//uart pin mux configure to default gpio
if(UARTx == UART0)
{
tmp_value = REG_RD(UART0_PIN_MUX_REG) & (~DW_UART0_GPIO_MASK);
REG_WR(UART0_PIN_MUX_REG, tmp_value);//gpio0/gpio1
}
else if(UARTx == UART1)
{
tmp_value = REG_RD(UART1_PIN_MUX_REG) & (~DW_UART1_GPIO_MASK);
REG_WR(UART1_PIN_MUX_REG, tmp_value);//gpio2/gpio3
}
else
{
tmp_value = REG_RD(UART2_PIN_MUX_REG) & (~DW_UART2_GPIO_MASK);
REG_WR(UART2_PIN_MUX_REG, tmp_value);//gpio6/gpio7 for a0v1; gpio12/gpio13 for a0v2
}
g_lega_uart_callback_handler[uart->port] = NULL;
return 0;
}

View file

@ -0,0 +1,131 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "lega_wdg.h"
void hw_watchdog_unlock(void)
{
WATCHDOG->LOCK = WDG_LOCK_TOKEN;
}
void hw_watchdog_lock(void)
{
WATCHDOG->LOCK = ~(WDG_LOCK_TOKEN);
}
void hw_watchdog_disable(void)
{
hw_watchdog_unlock();
WATCHDOG->CONTROL = 0x0;
WATCHDOG->LOAD = 0x0;
hw_watchdog_lock();
}
void hw_watchdog_isr(unsigned int delay)
{
hw_watchdog_unlock();
WATCHDOG->CONTROL = WDG_INTEN;
WATCHDOG->LOAD = delay;
hw_watchdog_lock();
}
void hw_watchdog_reset(unsigned int delay)
{
hw_watchdog_unlock();
WATCHDOG->CONTROL = WDG_RESEN | WDG_INTEN;
WATCHDOG->LOAD = delay;
hw_watchdog_lock();
}
void hw_watchdog_isr_clr(void)
{
hw_watchdog_unlock();
WATCHDOG->INTCLR = 0x1;
hw_watchdog_lock();
}
void WDG_IRQHandler(void)
{
lega_intrpt_enter();
lega_wdg_dev_t lega_wdg_dev;
lega_wdg_dev.port = 0;
lega_wdg_reload(&lega_wdg_dev);
lega_intrpt_exit();
}
/**
* This function will initialize the on board CPU hardware watch dog
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_wdg_init(lega_wdg_dev_t *wdg)
{
uint32_t reg_value;
if(NULL == wdg)
{
return -1;
}
if(0 == wdg->port)
{
// Set WDG Clock Enable
reg_value = REG_RD(PERI_CLK_CFG);
REG_WR(PERI_CLK_CFG, (reg_value|WDG_CLK_EN));
hw_watchdog_reset(wdg->config.timeout * (SYSTEM_CLOCK / 1000 / 2)); //1000 for ms, 2 for watchdog feature
NVIC_EnableIRQ(WDG_IRQn);
return 0;
}
else
{
return -1;
}
}
/**
* Reload watchdog counter.
*
* @param[in] wdg the watch dog device
*/
void lega_wdg_reload(lega_wdg_dev_t *wdg)
{
if(NULL == wdg)
{
return;
}
if(0 == wdg->port)
{
hw_watchdog_isr_clr();
}
}
/**
* This function performs any platform-specific cleanup needed for hardware watch dog.
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t lega_wdg_finalize(lega_wdg_dev_t *wdg)
{
uint32_t reg_value;
if(NULL == wdg)
{
return -1;
}
if(0 == wdg->port)
{
// Set WDG Clock Disable
reg_value = REG_RD(PERI_CLK_CFG);
REG_WR(PERI_CLK_CFG, (reg_value&(~WDG_CLK_EN)));
NVIC_DisableIRQ(WDG_IRQn);
hw_watchdog_disable();
return 0;
}
else
{
return -1;
}
}

View file

@ -0,0 +1,42 @@
#include <stdint.h>
#include "lega_cm4.h"
#include "rf_spi.h"
void spi_mst_write(uint16_t addr, uint16_t data)
{
uint32_t pre = 8<<28;
uint32_t start = 1 <<27;
uint32_t readnotwrite = 0 <<26;
uint32_t addr_t = addr <<16;
uint32_t data_t = data << 0;
uint32_t register_00 = pre | start | readnotwrite | addr_t | data_t ;
uint32_t var=0;
*((volatile int *) SPI_COMMAND)= register_00;
do
{
var =(*((volatile int *)SPI_COMMAND)) & (0x1 << 27);
}while(var);
}
uint16_t spi_mst_read(uint16_t addr)
{
uint32_t pre = 8 << 28;
uint32_t start = 1 <<27;
uint32_t readnotwrite = 1 <<26;
uint32_t addr_t = addr <<16;
uint32_t data_t = 0;
uint32_t register_00 = pre | start | readnotwrite | addr_t | data_t ;
uint32_t var=0;
*((volatile uint32_t *) SPI_COMMAND) = register_00;
do
{
var =(*((volatile uint32_t *) SPI_COMMAND) ) & (0x1 << 27);
}while(var);
return((uint16_t)*((volatile uint32_t *) SPI_RDATA));
}

View file

@ -0,0 +1 @@
for alios libs

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,673 @@
/**************************************************************************//**
* @file core_cm4_simd.h
* @brief CMSIS Cortex-M4 SIMD Header File
* @version V3.20
* @date 25. February 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
---------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __CORE_CM4_SIMD_H
#define __CORE_CM4_SIMD_H
/*******************************************************************************
* Hardware Abstraction Layer
******************************************************************************/
/* ################### Compiler specific Intrinsics ########################### */
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
Access to dedicated SIMD instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#define __SADD8 __sadd8
#define __QADD8 __qadd8
#define __SHADD8 __shadd8
#define __UADD8 __uadd8
#define __UQADD8 __uqadd8
#define __UHADD8 __uhadd8
#define __SSUB8 __ssub8
#define __QSUB8 __qsub8
#define __SHSUB8 __shsub8
#define __USUB8 __usub8
#define __UQSUB8 __uqsub8
#define __UHSUB8 __uhsub8
#define __SADD16 __sadd16
#define __QADD16 __qadd16
#define __SHADD16 __shadd16
#define __UADD16 __uadd16
#define __UQADD16 __uqadd16
#define __UHADD16 __uhadd16
#define __SSUB16 __ssub16
#define __QSUB16 __qsub16
#define __SHSUB16 __shsub16
#define __USUB16 __usub16
#define __UQSUB16 __uqsub16
#define __UHSUB16 __uhsub16
#define __SASX __sasx
#define __QASX __qasx
#define __SHASX __shasx
#define __UASX __uasx
#define __UQASX __uqasx
#define __UHASX __uhasx
#define __SSAX __ssax
#define __QSAX __qsax
#define __SHSAX __shsax
#define __USAX __usax
#define __UQSAX __uqsax
#define __UHSAX __uhsax
#define __USAD8 __usad8
#define __USADA8 __usada8
#define __SSAT16 __ssat16
#define __USAT16 __usat16
#define __UXTB16 __uxtb16
#define __UXTAB16 __uxtab16
#define __SXTB16 __sxtb16
#define __SXTAB16 __sxtab16
#define __SMUAD __smuad
#define __SMUADX __smuadx
#define __SMLAD __smlad
#define __SMLADX __smladx
#define __SMLALD __smlald
#define __SMLALDX __smlaldx
#define __SMUSD __smusd
#define __SMUSDX __smusdx
#define __SMLSD __smlsd
#define __SMLSDX __smlsdx
#define __SMLSLD __smlsld
#define __SMLSLDX __smlsldx
#define __SEL __sel
#define __QADD __qadd
#define __QSUB __qsub
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
((int64_t)(ARG3) << 32) ) >> 32))
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#include <cmsis_iar.h>
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
#include <cmsis_ccs.h>
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SSAT16(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
#define __USAT16(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
{
uint32_t result;
__ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
{
uint32_t result;
__ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SMLALD(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
#define __SMLALDX(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
__ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
#define __SMLSLD(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
#define __SMLSLDX(ARG1,ARG2,ARG3) \
({ \
uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \
__ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \
(uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2)
{
uint32_t result;
__ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
return(result);
}
#define __PKHBT(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
__ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
__RES; \
})
#define __PKHTB(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
if (ARG3 == 0) \
__ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
else \
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
__RES; \
})
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
{
int32_t result;
__ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
return(result);
}
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/
/* not yet supported */
/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/
#endif
/*@} end of group CMSIS_SIMD_intrinsics */
#endif /* __CORE_CM4_SIMD_H */
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,636 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V3.20
* @date 25. February 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
---------------------------------------------------------------------------*/
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i" : : : "memory");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i" : : : "memory");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
}
/** \brief Get IPSR Register
This function returns the content of the IPSR Register.
\return IPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f" : : : "memory");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f" : : : "memory");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
__ASM volatile ("");
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
/* Empty asm statement works as a scheduling barrier */
__ASM volatile ("");
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
__ASM volatile ("");
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

View file

@ -0,0 +1,688 @@
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V3.20
* @date 05. March 2013
*
* @note
*
******************************************************************************/
/* Copyright (c) 2009 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDERS AND CONTRIBUTORS 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.
---------------------------------------------------------------------------*/
#ifndef __CORE_CMINSTR_H
#define __CORE_CMINSTR_H
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#endif
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
/* TI CCS specific functions */
#include <cmsis_ccs.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/* Define macros for porting to both thumb1 and thumb2.
* For thumb1, use low register (r0-r7), specified by constrant "l"
* Otherwise, use general registers, specified by constrant "r" */
#if defined (__thumb__) && !defined (__thumb2__)
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
#define __CMSIS_GCC_USE_REG(r) "l" (r)
#else
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
#define __CMSIS_GCC_USE_REG(r) "r" (r)
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) ___INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
return __builtin_bswap32(value);
#else
uint32_t result;
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
return (short)__builtin_bswap16(value);
#else
uint32_t result;
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
return(result);
#endif
}
/** \brief Rotate Right in unsigned value (32 bit)
This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] value Value to rotate
\param [in] value Number of Bits to rotate
\return Rotated value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
return (op1 >> op2) | (op1 << (32 - op2));
}
/** \brief Breakpoint
This function causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __ASM volatile ("bkpt "#value)
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return(result);
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
__ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
#endif
return(result);
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
{
__ASM volatile ("clrex" ::: "memory");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
{
uint32_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */

View file

@ -0,0 +1,249 @@
/**
******************************************************************************
* @file misc.c
* @author MCD Application Team
* @version V1.4.0
* @date 04-August-2014
* @brief This file provides all the miscellaneous firmware functions (add-on
* to CMSIS functions).
*
* @verbatim
*
* ===================================================================
* How to configure Interrupts using driver
* ===================================================================
*
* This section provide functions allowing to configure the NVIC interrupts (IRQ).
* The Cortex-M4 exceptions are managed by CMSIS functions.
*
* 1. Configure the NVIC Priority Grouping using NVIC_PriorityGroupConfig()
* function according to the following table.
* The table below gives the allowed values of the pre-emption priority and subpriority according
* to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function
* ==========================================================================================================================
* NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description
* ==========================================================================================================================
* NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority
* | | | 4 bits for subpriority
* --------------------------------------------------------------------------------------------------------------------------
* NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority
* | | | 3 bits for subpriority
* --------------------------------------------------------------------------------------------------------------------------
* NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority
* | | | 2 bits for subpriority
* --------------------------------------------------------------------------------------------------------------------------
* NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority
* | | | 1 bits for subpriority
* --------------------------------------------------------------------------------------------------------------------------
* NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority
* | | | 0 bits for subpriority
* ==========================================================================================================================
*
* 2. Enable and Configure the priority of the selected IRQ Channels using NVIC_Init()
*
* @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
*
* @note IRQ priority order (sorted by highest to lowest priority):
* - Lowest pre-emption priority
* - Lowest subpriority
* - Lowest hardware priority (IRQ number)
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* 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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "misc.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver
* @{
*/
/** @defgroup MISC
* @brief MISC driver modules
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup MISC_Private_Functions
* @{
*/
/**
* @brief Configures the priority grouping: pre-emption priority and subpriority.
* @param NVIC_PriorityGroup: specifies the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
* 4 bits for subpriority
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
* 3 bits for subpriority
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
* 2 bits for subpriority
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
* 1 bits for subpriority
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
* 0 bits for subpriority
* @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
/**
* @brief Initializes the NVIC peripheral according to the specified
* parameters in the NVIC_InitStruct.
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
* function should be called before.
* @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
* the configuration information for the specified NVIC peripheral.
* @retval None
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub);
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}
/**
* @brief Sets the vector table location and Offset.
* @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory.
* This parameter can be one of the following values:
* @arg NVIC_VectTab_RAM: Vector Table in internal SRAM.
* @arg NVIC_VectTab_FLASH: Vector Table in internal FLASH.
* @param Offset: Vector Table base offset field. This value must be a multiple of 0x200.
* @retval None
*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
{
/* Check the parameters */
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));
SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
}
/**
* @brief Selects the condition for the system to enter low power mode.
* @param LowPowerMode: Specifies the new mode for the system to enter low power mode.
* This parameter can be one of the following values:
* @arg NVIC_LP_SEVONPEND: Low Power SEV on Pend.
* @arg NVIC_LP_SLEEPDEEP: Low Power DEEPSLEEP request.
* @arg NVIC_LP_SLEEPONEXIT: Low Power Sleep on Exit.
* @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_NVIC_LP(LowPowerMode));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
SCB->SCR |= LowPowerMode;
}
else
{
SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode);
}
}
/**
* @brief Configures the SysTick clock source.
* @param SysTick_CLKSource: specifies the SysTick clock source.
* This parameter can be one of the following values:
* @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
* @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
* @retval None
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -0,0 +1,181 @@
/**
******************************************************************************
* @file misc.h
* @author MCD Application Team
* @version V1.4.0
* @date 04-August-2014
* @brief This file contains all the functions prototypes for the miscellaneous
* firmware library functions (add-on to CMSIS functions).
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MISC_H
#define __MISC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "lega_cm4.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver
* @{
*/
/** @addtogroup MISC
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @brief NVIC Init Structure definition
*/
#define assert_param(expr) ((void)0)
typedef struct
{
uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled.
This parameter can be an enumerator of @ref IRQn_Type
enumeration (For the complete STM32 Devices IRQ Channels
list, please refer to stm32f4xx.h file) */
uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel
specified in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
A lower priority value indicates a higher priority */
uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified
in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
A lower priority value indicates a higher priority */
FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
will be enabled or disabled.
This parameter can be set either to ENABLE or DISABLE */
} NVIC_InitTypeDef;
/* Exported constants --------------------------------------------------------*/
/** @defgroup MISC_Exported_Constants
* @{
*/
/** @defgroup MISC_Vector_Table_Base
* @{
*/
#define NVIC_VectTab_RAM ((uint32_t)0x20000000)
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000)
#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \
((VECTTAB) == NVIC_VectTab_FLASH))
/**
* @}
*/
/** @defgroup MISC_System_Low_Power
* @{
*/
#define NVIC_LP_SEVONPEND ((uint8_t)0x10)
#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04)
#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02)
#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \
((LP) == NVIC_LP_SLEEPDEEP) || \
((LP) == NVIC_LP_SLEEPONEXIT))
/**
* @}
*/
/** @defgroup MISC_Preemption_Priority_Group
* @{
*/
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
0 bits for subpriority */
#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
((GROUP) == NVIC_PriorityGroup_1) || \
((GROUP) == NVIC_PriorityGroup_2) || \
((GROUP) == NVIC_PriorityGroup_3) || \
((GROUP) == NVIC_PriorityGroup_4))
#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10)
#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10)
#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF)
/**
* @}
*/
/** @defgroup MISC_SysTick_clock_source
* @{
*/
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8))
/**
* @}
*/
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
#ifdef __cplusplus
}
#endif
#endif /* __MISC_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -0,0 +1,229 @@
/**
****************************************************************************************
*
* @file lega_cm4.h
*
* @brief define arm cm4 SOC architecture
*
* Copyright (C) ASR
*
****************************************************************************************
*/
/************************* **************************************/
#ifndef __LEGA_CM4_H__
#define __LEGA_CM4_H__
#ifdef __cplusplus
extern "C" {
#endif
#define __CM0_REV 0 /*!< Core Revision r0p0 */
#define __MPU_PRESENT 0 /*!< legawifi do not provide MPU */
#define __NVIC_PRIO_BITS 3 /*!< legawifi uses 3 Bits for the Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
//hightest interrupt priority is configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY&((1<<__NVIC_PRIO_BITS)-1)=5
//lowest interrupt priority is configLIBRARY_LOWEST_INTERRUPT_PRIORITY&((1<<__NVIC_PRIO_BITS)-1)=7
//set normal interrupt priority 6
#define configLIBRARY_NORMAL_INTERRUPT_PRIORITY 6
typedef enum IRQn
{
/************** Processor Exceptions Numbers ******************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */
/****** Interrupt Numbers *******************************************************/
CEVA_RW_IP_IRQn = 0, /*!< CEVA RW IP Interrupt */
SLEEP_IRQn = 1, /*!< Sleep Wake-Up Interrupt */
WDG_IRQn = 2, /*!< Window WatchDog */
FLASH_IRQn = 3, /*!< FLASH Interrupt */
GPIO_IRQn = 4, /*!< GPIO Interrupt */
TIMER_IRQn = 5, /*!< Timer Interrupt */
CRYPTOCELL310_IRQn = 6, /*!< CryptoCell 310 Interrupt */
DMA_CTRL_IRQn = 7, /*!< Generic DMA Ctrl Interrupt */
UART0_IRQn = 8, /*!< UART0 Interrupt */
UART1_IRQn = 9, /*!< UART1 Interrupt */
UART2_IRQn = 10, /*!< UART2 Interrupt */
SPI0_IRQn = 11, /*!< SPI0 Interrupt */
SPI1_IRQn = 12, /*!< SPI1 Interrupt */
SPI2_IRQn = 13, /*!< SPI2 */
I2C0_IRQn = 14, /*!< I2C0 Interrupt */
I2C1_IRQn = 15, /*!< I2C1 Interrupt */
SDIO_IRQn = 16, /*!< SDIO Combined Interrupt */
D_APLL_UNLOCK_IRQn = 17, /*!< RF added: D_APLL_UNLOCK Interrupt */
D_SX_UNLOCK_IRQn = 18, /*!< RF added: D_SX_UNLOCK Interrupt */
PLF_WAKEUP_IRQn = 23, /*!< WiFi Platform Wake-Up Interrupt */
} IRQn_Type;
#ifdef LEGA_CM4
#include "core_cm4.h"
#endif
#include <stdint.h>
// ---------------------------------------------------------------------------
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
#define XTAL_26M 26000000
extern uint32_t system_bus_clk;
extern uint32_t system_core_clk;
#if defined LEGA_A0V1
#define SYSTEM_CLOCK (26000000)
#elif defined LEGA_A0V2
#define SYSTEM_CORE_CLOCK system_core_clk
#define SYSTEM_CLOCK system_bus_clk
#endif
#define SYSTEM_CLOCK_NORMAL (80000000)
#define SYSTEM_CORE_CLOCK_INIT ( 52000000)
#define SYSTEM_CORE_CLOCK_HIGH (160000000)
#define SYSTEM_BUS_CLOCK_INIT (52000000)
#define SYSTEM_BUS_CLOCK_HIGH (80000000)
#define HAPS_FPGA 0
#define V7_FPGA 1
#define FPGA_PLATFORM V7_FPGA
#if (defined LEGA_A0V1)
#define PINMUX_CTRL_REG0 0x40000038 //pad0-7
#define PINMUX_CTRL_REG1 0x4000003C //pad8-15
#define PINMUX_CTRL_REG2 0x40000048 //pad16-23
#define PINMUX_CTRL_REG3 0x4000004C //pad24-31
#elif (defined LEGA_A0V2)
#define PINMUX_CTRL_REG0 0x40000004 //pad0-7
#define PINMUX_CTRL_REG1 0x40000008 //pad8-15
#define PINMUX_CTRL_REG2 0x4000000C //pad16-23
#define PINMUX_CTRL_REG3 0x40000010 //pad24-31
#endif
#define SYS_REG_BASE 0x40000000
#define SYS_REG_BASE_FLASH_CLK ((SYS_REG_BASE + 0x808))
#define PERI_CLK_CFG (SYS_REG_BASE + 0x850)
#define SYS_REG_BASE_C310_CLK ((SYS_REG_BASE + 0x900))
#define REG_INTERRUPT_ENABLE (SYS_REG_BASE + 0x944)
#define SYS_CRM_SYS_CLK_CTRL1 *((volatile uint32_t *)(SYS_REG_BASE + 0x950))
#define SYS_CRM_REG_0x804 *((volatile uint32_t *)(SYS_REG_BASE + 0x804))
#define SYS_CRM_UART2_FRAC_DIV *((volatile uint32_t *)(SYS_REG_BASE + 0x82C))
#define ALWAYS_ON_REGFILE 0x40000A00
#define REG_AHB_BUS_CTRL *((volatile uint32_t *)(ALWAYS_ON_REGFILE + 0x90))
#define REG_PLF_WAKEUP_INT_EN (0x1<<23)
#define SDIO_HCLK_EN (1 << 4)
#define PWM_CLK_EN (1 << 2)
#define WDG_CLK_EN (1 << 1)
#define TIMER_SCLK_EN 0x1
#define SYS_CRM_WIFI_BLK_CLK *((volatile uint32_t *)(SYS_REG_BASE + 0x85C))
#define MDM_CLKGATEFCTRL0_ADDR 0x60C00874
#define MDM_CLKGATEFCTRL0 *((volatile uint32_t *)(MDM_CLKGATEFCTRL0_ADDR))
#define RTC_REG_RCO32K_ADDR 0x40000A44
#define RTC_REG_RCO32K *((volatile uint32_t *)(RTC_REG_RCO32K_ADDR))
#define SYS_CRM_CLR_HCLK_REC *((volatile uint32_t *)(SYS_REG_BASE + 0x844))
#define TRX_PD_CTRL1_REG_ADDR 0x06
#define TRX_PD_CTRL2_REG_ADDR 0x07
#define APLL_PD_CTRL_REG_ADDR 0x0D
#define APLL_RST_CTRL_REG_ADDR 0x0E
#define XO_PD_CTRL_REG_ADDR 0x0F
#define APLL_CLK_PHY_REG_ADDR 0x6B
#define APLL_FCAL_FSM_CTRL_ADDR 0x6E
#ifdef LEGA_A0V1
#define _FLASH_DIRECT_BOOT_EN_
#endif
//efuse memory
typedef struct
{
uint8_t mac_addr0[6]; //0x90-0x95
uint8_t freq_err; //0x96
uint8_t tmmt1; //0x97
uint8_t tmmt2; //0x98
uint8_t cus_tx_pwr[19]; //0x99-0xab
uint8_t cal_tx_pwr0[6]; //0xac-0xb1
uint8_t cus_tx_total_pwr[3]; //0xb2-0xb4
uint8_t cal_tx_evm0[6]; //0xb5-0xba
uint8_t reserved1[5]; //0xbb-0xbf
uint8_t mac_addr1[6]; //0xc0-0xc5
uint8_t mac_addr2[6]; //0xc6-0xcb
uint8_t cal_tx_pwr1[6]; //0xcc-0xd1
uint8_t cal_tx_evm1[6]; //0xd2-0xd7
uint8_t cal_tx_pwr2[6]; //0xd8-0xdd
uint8_t cal_tx_evm2[6]; //0xde-0xe3
uint8_t reserved2[12]; //0xe4-0xef
}efuse_info_t;
#define EFUSE_INFO_START_ADDR 0x90
#define EFUSE_INFO_LEN (sizeof(efuse_info_t))
#ifdef _FLASH_DIRECT_BOOT_EN_
#define BOOTLOADER_FLASH_START_ADDR 0x00000000
#define INFO_FLASH_START_ADDR 0x00010000
#define APP_FLASH_START_ADDR 0x00040000
#define OTA_FLASH_START_ADDR 0x00100000
#define KV_FLASH_START_ADDR 0x001E0000
#define OLL_FLASH_START_ADDR 0x001E4000
#else
#define BOOTLOADER_FLASH_START_ADDR 0x10000000
#ifdef VENDOR_MXCHIP
#define INFO_FLASH_START_ADDR 0x10005000
#define KV_FLASH_START_ADDR 0x10006000
#define APP_FLASH_START_ADDR 0x1000A000
#define OTA_FLASH_START_ADDR 0x10100000
#define OLL_FLASH_START_ADDR 0x101E4000
#else
#define INFO_FLASH_START_ADDR 0x10010000
#define APP_FLASH_START_ADDR 0x10040000
#define OTA_FLASH_START_ADDR 0x10100000
#define KV_FLASH_START_ADDR 0x101E0000
#define OLL_FLASH_START_ADDR 0x101E4000
#endif
#endif
#ifdef VENDOR_MXCHIP
#define BOOTLOADER_MAX_SIZE 0x5000
#define INFO_MAX_SIZE 0x1000
#define KV_MAX_SIZE 0x4000
#define APP_MAX_SIZE 0xF6000
#define OTA_MAX_SIZE 0xA4000
#define OLL_MAX_SIZE 0x1000
#else
#define BOOTLOADER_MAX_SIZE 0x10000
#define INFO_MAX_SIZE 0x1000
#define KV_MAX_SIZE 0x20000
#define APP_MAX_SIZE 0xC0000
#define OTA_MAX_SIZE 0xC0000
#define OLL_MAX_SIZE 0x1000
#endif
#ifdef ALIOS_SUPPORT
#include <k_api.h>
#define lega_intrpt_enter() krhino_intrpt_enter()
#define lega_intrpt_exit() krhino_intrpt_exit()
#else
#define lega_intrpt_enter()
#define lega_intrpt_exit()
#endif
#endif

View file

@ -0,0 +1,89 @@
#ifndef __PMU_H
#define __PMU_H
#include "stdint.h"
typedef enum pmu_state
{
PMU_STATE_ACTIVE = 0,
PMU_STATE_MODEMSLEEP,
PMU_STATE_LIGHTSLEEP,
PMU_STATE_DEEPSLEEP,
PMU_STATE_LAST
}pmu_state_t;
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) static inline void __WFI__(void)
{
__asm volatile( "dsb" );
__asm volatile( "wfi" );
__asm volatile( "isb" );
}
/** @brief get current RTC counter, only used when RTC enabled.
*
* @return : current RTC counter
*/
uint32_t lega_drv_rtc_counter_get();
/** @brief get MAX RTC counter we can set, only used when RTC enabled.
*
* @return : MAX RTC counter we can set
*/
uint32_t lega_drv_rtc_max_ticks_get();
/** @brief get MAX RTC counter we can set, only used when RTC enabled.
* @param cc_counter: RTC counter to set.
* @param whitch state you want goto, default modemsleep.
* @return 0: set OK.
* @return other: set error.
*/
uint16_t lega_drv_rtc_cc_set(uint32_t cc_counter, pmu_state_t pmu_state);
/** @brief enable RTC clock, used after lega_drv_rtc_cc_set.
*/
void lega_drv_rtc_enable();
/** @brief goto sleep state.
* @param pmu_state: state to set:MODEMSLEEP/LIGHTSLEEP/DEEPSLEEP.
* @param pmu_state: state to set:MODEMSLEEP/LIGHTSLEEP/DEEPSLEEP.
*/
void lega_drv_goto_sleep(pmu_state_t pmu_state);
/** @brief goto active state, call when waked from SLEEP states.
*/
void lega_drv_goto_active();
#endif //__PMU_H

View file

@ -0,0 +1,18 @@
#ifndef __SYSTEM_CM4_H
#define __SYSTEM_CM4_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lega_cm4.h"
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
extern void lega_system_reset(void);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,47 @@
#ifndef __SYSTICK_DELAY_H
#define __SYSTICK_DELAY_H
#include "lega_cm4.h"
#ifdef ALIOS_SUPPORT
uint32_t lega_systick_csr_get();
void lega_systick_csr_set(uint32_t ctrl);
#endif
void delay_init(uint8_t SYSCLK);
void delay_us(u32 nus);
void delay_ms(u32 nms);
void delay_xms(u32 nms);
#endif //__SYSTICK_DELAY_H

View file

@ -0,0 +1,67 @@
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
__asm void WFI_SET(void)
{
WFI;
}
__asm void INTX_DISABLE(void)
{
CPSID I
BX LR
}
__asm void INTX_ENABLE(void)
{
CPSIE I
BX LR
}
__asm void MSR_MSP(u32 addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
// below code is for no need to select microlib
#if 0
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif

View file

@ -0,0 +1,67 @@
#include <sys/stat.h>
////////////////////////////////////
int _fstat (int fd, struct stat *pStat)
{
pStat->st_mode = S_IFCHR;
return 0;
}
////////////////////////////////////
int _close(int i)
{
return -1;
}
/////////////////////////////////////
int _write (int fd, char *pBuffer, int size)
{
int i;
for ( i = 0; i < size; i++)
{
//USART_SendData(USART1, pBuffer[i]);
//uart_put_char(pBuffer[i]);
}
return size;
}
///////////////////////////////////
int _isatty (int fd)
{
return 1;
}
/////////////////////////////////
int _lseek(int i, int k, int j)
{
return -1;
}
////////////////////////////////
int _read (int fd, char *pBuffer, int size)
{
int i;
for (i = 0; i < size; i++)
{
//pBuffer[i] = UART_ReceiveData(UART1);
}
return size;
}
////////////////////////////////
caddr_t _sbrk(int increment)
{
extern char end asm("end");
register char *pStack asm("sp");
static char *s_pHeapEnd;
if (!s_pHeapEnd)
s_pHeapEnd = &end;
if (s_pHeapEnd + increment > pStack)
return (caddr_t)-1;
char *pOldHeapEnd = s_pHeapEnd;
s_pHeapEnd += increment;
return (caddr_t)pOldHeapEnd;
}
/************end *************************/

View file

@ -0,0 +1,34 @@
#include "lega_cm4.h"
#include "core_cm4.h"
void lega_system_reset(void)
{
//disable irq when reboot
__disable_irq();
#ifdef HIGHFREQ_MCU160_SUPPORT
if(system_core_clk == SYSTEM_CORE_CLOCK_HIGH)
lega_clk_sel_low();
#endif
NVIC_SystemReset();
}
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
}
void SystemCoreClockUpdate(void)
{
}
/********END OF FILE ***********/

View file

@ -0,0 +1,119 @@
#include "systick_delay.h"
#ifdef ALIOS_SUPPORT
#include <stdio.h>
#include <k_config.h>
#include <k_err.h>
#include <k_sys.h>
#include <k_time.h>
#else
#include "FreeRTOS.h"
#include "task.h"
#endif
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
static u8 fac_us=0;
static u16 fac_ms=0;
#ifdef ALIOS_SUPPORT
void SysTick_Handler(void)
{
krhino_intrpt_enter();
krhino_tick_proc();
krhino_intrpt_exit();
}
uint32_t lega_systick_csr_get()
{
uint32_t ul_systick_ctrl;
ul_systick_ctrl = SysTick->CTRL;
return ul_systick_ctrl;
}
void lega_systick_csr_set(uint32_t ctrl)
{
SysTick->CTRL = ctrl;
}
void delay_init(u8 SYSCLK)
{
u32 reload;
//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
fac_us=SYSCLK;
reload=SYSCLK;
reload= reload*1000000/RHINO_CONFIG_TICKS_PER_SECOND;
fac_ms=1000/RHINO_CONFIG_TICKS_PER_SECOND;
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;
SysTick->LOAD=reload;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
}
#else
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}
void delay_init(u8 SYSCLK)
{
u32 reload;
//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
fac_us=SYSCLK;
reload=SYSCLK;
reload= reload*1000000/configTICK_RATE_HZ;
fac_ms=1000/configTICK_RATE_HZ;
SysTick_Config(reload);
}
#endif
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;
ticks=nus*fac_us;
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
};
}
#ifndef ALIOS_SUPPORT
void delay_ms(u32 nms)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
{
if(nms>=fac_ms)
{
vTaskDelay(nms/fac_ms);
}
nms%=fac_ms;
}
delay_us((u32)(nms*1000));
}
#endif
void delay_xms(u32 nms)
{
u32 i;
for(i=0;i<nms;i++) delay_us(1000);
}

View file

@ -0,0 +1,216 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
#ifndef CRYS_ERROR_H
#define CRYS_ERROR_H
#include "ssi_pal_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/*! @file
@brief This module defines the error return code types and the numbering spaces of the error codes
for each module of the layers listed below.
*/
/*! The definitions of the error number space used for the different modules */
/* ........... Error base numeric mapping definitions ................... */
/* ----------------------------------------------------------------------- */
/* The global error base number */
#define CRYS_ERROR_BASE 0x00F00000UL
/* The error range number assigned for each layer */
#define CRYS_ERROR_LAYER_RANGE 0x00010000UL
/* The error range number assigned to each module on its specified layer */
#define CRYS_ERROR_MODULE_RANGE 0x00000100UL
/* Defines the layer index for the error mapping */
#define CRYS_LAYER_ERROR_IDX 0x00UL
#define LLF_LAYER_ERROR_IDX 0x01UL
#define GENERIC_ERROR_IDX 0x05UL
/* Defines the module index for error mapping */
#define AES_ERROR_IDX 0x00UL
#define DES_ERROR_IDX 0x01UL
#define HASH_ERROR_IDX 0x02UL
#define HMAC_ERROR_IDX 0x03UL
#define RSA_ERROR_IDX 0x04UL
#define DH_ERROR_IDX 0x05UL
#define ECPKI_ERROR_IDX 0x08UL
#define RND_ERROR_IDX 0x0CUL
#define COMMON_ERROR_IDX 0x0DUL
#define KDF_ERROR_IDX 0x11UL
#define HKDF_ERROR_IDX 0x12UL
#define AESCCM_ERROR_IDX 0x15UL
#define FIPS_ERROR_IDX 0x17UL
#define PKA_MODULE_ERROR_IDX 0x21UL
#define CHACHA_ERROR_IDX 0x22UL
#define EC_MONT_EDW_ERROR_IDX 0x23UL
#define CHACHA_POLY_ERROR_IDX 0x24UL
#define POLY_ERROR_IDX 0x25UL
#define SRP_ERROR_IDX 0x26UL
/* .......... defining the error spaces for each module on each layer ........... */
/* ------------------------------------------------------------------------------ */
/* AES module on the CRYS layer base address - 0x00F00000 */
#define CRYS_AES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * AES_ERROR_IDX ) )
/* DES module on the CRYS layer base address - 0x00F00100 */
#define CRYS_DES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * DES_ERROR_IDX ) )
/* HASH module on the CRYS layer base address - 0x00F00200 */
#define CRYS_HASH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * HASH_ERROR_IDX ) )
/* HMAC module on the CRYS layer base address - 0x00F00300 */
#define CRYS_HMAC_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * HMAC_ERROR_IDX ) )
/* PKI RSA module on the CRYS layer base address - 0x00F00400 */
#define CRYS_RSA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * RSA_ERROR_IDX ) )
/* DH module on the CRYS layer base address - 0x00F00500 */
#define CRYS_DH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * DH_ERROR_IDX ) )
/* ECPKI module on the CRYS layer base address - 0x00F00800 */
#define CRYS_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) )
/* ECPKI module on the LLF layer base address - 0x00F10800 */
#define LLF_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) )
/* RND module on the CRYS layer base address - 0x00F00C00 */
#define CRYS_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) )
/* RND module on the LLF layer base address - 0x00F10C00 */
#define LLF_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) )
/* COMMMON module on the CRYS layer base address - 0x00F00D00 */
#define CRYS_COMMON_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * COMMON_ERROR_IDX ) )
/* KDF module on the CRYS layer base address - 0x00F01100 */
#define CRYS_KDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * KDF_ERROR_IDX ) )
/* KDF module on the CRYS layer base address - 0x00F01100 */
#define CRYS_HKDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * HKDF_ERROR_IDX ) )
/* AESCCM module on the CRYS layer base address - 0x00F01500 */
#define CRYS_AESCCM_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * AESCCM_ERROR_IDX ) )
/* FIPS module on the CRYS layer base address - 0x00F01700 */
#define CRYS_FIPS_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * FIPS_ERROR_IDX ) )
/* SELF TEST module on the CRYS layer base address - 0x00F02100 */
#define PKA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * PKA_MODULE_ERROR_IDX ) )
/* CRYS CHACHA module on the CRYS layer base address - */
#define CRYS_CHACHA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * CHACHA_ERROR_IDX ) )
/* CRYS CHACHA module on the CRYS layer base address - */
#define CRYS_CHACHA_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * CHACHA_POLY_ERROR_IDX ) )
/* CRYS CHACHA module on the CRYS layer base address - */
#define CRYS_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * POLY_ERROR_IDX ) )
/* CRYS SRP module on the CRYS layer base address - */
#define CRYS_SRP_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * SRP_ERROR_IDX ) )
/* CRYS EC MONT_EDW module on the CRYS layer base address - */
#define CRYS_EC_MONT_EDW_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \
(CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \
(CRYS_ERROR_MODULE_RANGE * EC_MONT_EDW_ERROR_IDX ) )
/* User generic layer base address - 0x00F50000 */
#define GENERIC_ERROR_BASE ( CRYS_ERROR_BASE + (CRYS_ERROR_LAYER_RANGE * GENERIC_ERROR_IDX) )
#define CRYS_FATAL_ERROR (GENERIC_ERROR_BASE + 0x00UL)
#define CRYS_OUT_OF_RESOURCE_ERROR (GENERIC_ERROR_BASE + 0x01UL)
#define CRYS_ILLEGAL_RESOURCE_VAL_ERROR (GENERIC_ERROR_BASE + 0x02UL)
/* ............ The OK (success) definition ....................... */
#define CRYS_OK 0
#define SASI_CRYS_RETURN_ERROR(retCode, retcodeInfo, funcHandler) \
((retCode) == 0 ? CRYS_OK : funcHandler(retCode, retcodeInfo))
/************************ Enums ********************************/
/************************ Typedefs ****************************/
/*! The typedef definition of all of the error codes that are returned from the CRYS functions */
typedef uint32_t CRYSError_t;
/************************ Structs ******************************/
/************************ Public Variables **********************/
/************************ Public Functions **********************/
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,354 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
#ifndef CRYS_RND_H
#define CRYS_RND_H
#include "crys_error.h"
#include "ssi_aes.h"
#ifdef __cplusplus
extern "C"
{
#endif
/*!
@file
@brief This file contains the CRYS APIs used for random number generation.
The random-number generation module implements referenced standard [SP800-90].
*/
/************************ Defines ******************************/
/*! Maximal reseed counter - indicates maximal number of
requests allowed between reseeds; according to NIST 800-90
it is (2^48 - 1), our restriction is : (0xFFFFFFFF - 0xF).*/
#define CRYS_RND_MAX_RESEED_COUNTER (0xFFFFFFFF - 0xF)
/* maximal requested size counter (12 bits active) - maximal count
of generated random 128 bit blocks allowed per one request of
Generate function according NIST 800-90 it is (2^12 - 1) = 0x3FFFF */
#define CRYS_RND_REQUESTED_SIZE_COUNTER 0x3FFFF
/*! AES output block size in words. */
#define CRYS_RND_AES_BLOCK_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS
/* RND seed and additional input sizes */
#define CRYS_RND_SEED_MAX_SIZE_WORDS 12
#ifndef CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS
#define CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS CRYS_RND_SEED_MAX_SIZE_WORDS
#endif
/* Max size of generated random vector in bits according uint16_t type of *
* input size parameter in CRYS_RND_Generate function */
#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BYTES 0xFFFF
/* allowed sizes of AES Key, in words */
#define CRYS_RND_AES_KEY_128_SIZE_WORDS 4
#define CRYS_RND_AES_KEY_192_SIZE_WORDS 6
#define CRYS_RND_AES_KEY_256_SIZE_WORDS 8
/* Definitions of temp buffer for RND_DMA version of CRYS_RND */
/*******************************************************************/
/* Definitions of temp buffer for DMA version of CRYS_RND */
#define CRYS_RND_WORK_BUFFER_SIZE_WORDS 1528 //25
/*! A definition for RAM buffer to be internally used in instantiation (or reseeding) operation. */
typedef struct
{
/* include the specific fields that are used by the low level */
uint32_t crysRndWorkBuff[CRYS_RND_WORK_BUFFER_SIZE_WORDS];
}CRYS_RND_WorkBuff_t;
#define CRYS_RND_EntropyEstimatData_t CRYS_RND_WorkBuff_t
#define crysRndEntrIntBuff crysRndWorkBuff
/* RND source buffer inner (entrpopy) offset */
#define CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS 2
/* Max size for one RNG operation */
#define CRYS_RND_MAX_SIZE_OF_OUTPUT_BYTES 3*1024
/* Size of the expected output buffer used by FIPS KAT */
#define CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE 64
/************************ Enumerators ****************************/
/* Definition of Fast or Slow mode of random generator (TRNG)*/
typedef enum
{
CRYS_RND_Fast = 0,
CRYS_RND_Slow = 1,
CRYS_RND_ModeLast = 0x7FFFFFFF,
} CRYS_RND_mode_t;
/************************ Structs *****************************/
/* The internal state of DRBG mechanism based on AES CTR and CBC-MAC
algorithms. It is set as global data defined by the following
structure */
typedef struct
{
/* Seed buffer, consists from concatenated Key||V: max size 12 words */
uint32_t Seed[CRYS_RND_SEED_MAX_SIZE_WORDS];
/* Previous value for continuous test */
uint32_t PreviousRandValue[SASI_AES_BLOCK_SIZE_IN_WORDS];
/* AdditionalInput buffer max size = seed max size words + 4w for padding*/
uint32_t PreviousAdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+3];
uint32_t AdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+4];
uint32_t AddInputSizeWords; /* size of additional data set by user, words */
/* entropy source size in words */
uint32_t EntropySourceSizeWords;
/* reseed counter (32 bits active) - indicates number of requests for entropy
since instantiation or reseeding */
uint32_t ReseedCounter;
/* key size: 4 or 8 words according to security strength 128 bits or 256 bits*/
uint32_t KeySizeWords;
/* State flag (see definition of StateFlag above), containing bit-fields, defining:
- b'0: instantiation steps: 0 - not done, 1 - done;
- 2b'9,8: working or testing mode: 0 - working, 1 - KAT DRBG test, 2 -
KAT TRNG test;
b'16: flag defining is Previous random valid or not:
0 - not valid, 1 - valid */
uint32_t StateFlag;
/* Trng processing flag - indicates which ROSC lengths are:
- allowed (bits 0-3);
- total started (bits 8-11);
- processed (bits 16-19);
- started, but not processed (bits24-27) */
uint32_t TrngProcesState;
/* validation tag */
uint32_t ValidTag;
/* Rnd source entropy size in bits */
uint32_t EntropySizeBits;
} CRYS_RND_State_t;
/*! The RND Generate vector function pointer type definition.
The prototype intendent for External and CRYS internal RND functions
pointers definitions.
Full description can be found in ::CRYS_RND_GenerateVector function API. */
typedef uint32_t (*SaSiRndGenerateVectWorkFunc_t)( \
CRYS_RND_State_t *rndState_ptr, /*context*/ \
uint16_t outSizeBytes, /*in*/ \
uint8_t *out_ptr /*out*/);
/*! definition of RND context that includes CRYS RND state structure and a function pointer for rnd generate function */
typedef struct
{
/* The pointer to internal state of RND */
CRYS_RND_State_t rndState;
/* The pointer to user given function for generation random vector */
SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc;
} CRYS_RND_Context_t;
/*! Required for internal FIPS verification for PRNG KAT. */
typedef struct
{
CRYS_RND_WorkBuff_t rndWorkBuff;
uint8_t rndOutputBuff[CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE];
} CRYS_PrngFipsKatCtx_t;
/*****************************************************************************/
/********************** Public Functions *************************/
/*****************************************************************************/
/*!
@brief This function initializes the RND context.
It must be called at least once prior to using this context with any API that requires it as a parameter (e.g., other RND APIs, asymmetric
cryptography key generation and signatures).
It is called as part of ARM TrustZone CryptoCell library initialization, which initializes and returns the primary RND context.
This primary context can be used as a single global context for all RND needs.
Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads).
The call to this function must be followed by a call to ::CRYS_RND_SetGenerateVectorFunc API to set the generate vector function.
It implements referenced standard [SP800-90] - 10.2.1.3.2 - CTR-DRBG Instantiate algorithm using AES (FIPS-PUB 197) and Derivation Function (DF).
\note Additional data can be mixed with the random seed (personalization data or nonce). If required, this data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_Instantiation(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer allocated by the user, which is used to
maintain the RND state, as well as pointers to the functions used for
random vector generation. This context must be saved and provided as a
parameter to any API that uses the RND module.
\note the context must be cleared before sent to the function. */
CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */
);
/*!
@brief Clears existing RNG instantiation state.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_UnInstantiation(
CRYS_RND_Context_t *rndContext_ptr /*!< [in/out] Pointer to the RND context buffer. */
);
/*!
@brief This function is used for reseeding the RNG with additional entropy and additional user-provided input.
(additional data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API).
It implements referenced standard [SP800-90] - 10.2.1.4.2 - CTR-DRBG Reseeding algorithm, using AES (FIPS-PUB 197) and Derivation Function (DF).
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_Reseeding(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer. */
CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in/out] Scratchpad for the RND module's work. */
);
/****************************************************************************************/
/*!
@brief Generates a random vector according to the algorithm defined in referenced standard [SP800-90] - 10.2.1.5.2 - CTR-DRBG.
The generation algorithm uses AES (FIPS-PUB 197) and Derivation Function (DF).
\note
<ul id="noteb"><li> The RND module must be instantiated prior to invocation of this API.</li>
<li> In the following cases, Reseeding operation must be performed prior to vector generation:</li>
<ul><li> Prediction resistance is required.</li>
<li> The function returns CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR, stating that the Reseed Counter has passed its upper-limit (2^32-2).</li></ul></ul>
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_GenerateVector(
CRYS_RND_State_t *rndState_ptr, /*!< [in/out] Pointer to the RND state structure, which is part of the RND context structure.
Use rndContext->rndState field of the context for this parameter. */
uint16_t outSizeBytes, /*!< [in] The size in bytes of the random vector required. The maximal size is 2^16 -1 bytes. */
uint8_t *out_ptr /*!< [out] The pointer to output buffer. */
);
/****************************************************************************************/
/*!
@brief This function sets the RND vector generation function into the RND context.
It must be called after ::CRYS_RND_Instantiation, and prior to any other API that requires the RND context as parameter.
It is called as part of ARM TrustZone CryptoCell library initialization, to set the RND vector generation function into the primary RND context,
after ::CRYS_RND_Instantiation is called.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CRYSError_t CRYS_RND_SetGenerateVectorFunc(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer allocated by the user,
which is used to maintain the RND state as well as pointers
to the functions used for random vector generation. */
SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc /*!< [in] Pointer to the random vector generation function.
The pointer should point to the ::CRYS_RND_GenerateVector function. */
);
/**********************************************************************************************************/
/*!
@brief Generates a random vector with specific limitations by testing candidates (described and used in FIPS 186-4: B.1.2, B.4.2 etc.).
This function will draw a random vector, compare it to the range limits, and if within range - return it in rndVect_ptr.
If outside the range, the function will continue retrying until a conforming vector is found, or the maximal retries limit is exceeded.
If maxVect_ptr is provided, rndSizeInBits specifies its size, and the output vector must conform to the range [1 < rndVect < maxVect_ptr].
If maxVect_ptr is NULL, rndSizeInBits specifies the exact required vector size, and the output vector must be the exact same
bit size (with its most significant bit = 1).
\note
The RND module must be instantiated prior to invocation of this API.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_GenerateVectorInRange(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer. */
uint32_t rndSizeInBits, /*!< [in] The size in bits of the random vector required. The allowed size in range 2 <= rndSizeInBits < 2^19-1, bits. */
uint8_t *maxVect_ptr, /*!< [in] Pointer to the vector defining the upper limit for the random vector output, Given as little-endian byte array.
If not NULL, its actual size is treated as [(rndSizeInBits+7)/8] bytes. */
uint8_t *rndVect_ptr /*!< [in/out] Pointer to the output buffer for the random vector. Must be at least [(rndSizeInBits+7)/8] bytes.
Treated as little-endian byte array. */
);
/*************************************************************************************/
/*!
@brief Used for adding additional input/personalization data provided by the user,
to be later used by the ::CRYS_RND_Instantiation/::CRYS_RND_Reseeding/::CRYS_RND_GenerateVector functions.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_AddAdditionalInput(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer. */
uint8_t *additonalInput_ptr, /*!< [in] The Additional Input buffer. */
uint16_t additonalInputSize /*!< [in] The size of the Additional Input buffer. Must be <= 48, and a multiple of 4. */
);
/*!
@brief The CRYS_RND_EnterKatMode function sets KAT mode bit into StateFlag of global CRYS_RND_WorkingState structure.
The user must call this function before calling functions performing KAT tests.
\note Total size of entropy and nonce must be not great than: ::CRYS_RND_MAX_KAT_ENTROPY_AND_NONCE_SIZE, defined.
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_EnterKatMode(
CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer. */
uint8_t *entrData_ptr, /*!< [in] Entropy data. */
uint32_t entrSize, /*!< [in] Entropy size in bytes. */
uint8_t *nonce_ptr, /*!< [in] Nonce. */
uint32_t nonceSize, /*!< [in] Entropy size in bytes. */
CRYS_RND_WorkBuff_t *workBuff_ptr /*!< [out] RND working buffer, must be the same buffer, which should be passed into
Instantiation/Reseeding functions. */
);
/**********************************************************************************************************/
/*!
@brief The CRYS_RND_DisableKatMode function disables KAT mode bit into StateFlag of global CRYS_RND_WorkingState structure.
The user must call this function after KAT tests before actual using RND module (Instantiation etc.).
@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C void CRYS_RND_DisableKatMode(
CRYS_RND_Context_t *rndContext_ptr /*!< [in/out] Pointer to the RND context buffer. */
);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef CRYS_RND_H */

View file

@ -0,0 +1,25 @@
#ifndef _LEGA_AES_H_
#define _LEGA_AES_H_
#include "ssi_aes_defs.h"
#include "ssi_aes.h"
typedef struct {
char *p_workspace;
uint8_t key_data[SASI_AES_KEY_MAX_SIZE_IN_BYTES];
uint8_t key_size;
SaSiAesIv_t iv_counter;
uint8_t *input_data;
uint8_t *output_data;
uint16_t data_size;
SaSiAesOperationMode_t operation_mode;
SaSiAesEncryptMode_t enc_dec_mode;
uint32_t output_datasize;
} lega_aes_dev_t;
int lega_aes_init(lega_aes_dev_t *aes_crypt);
int lega_aes_crypt(lega_aes_dev_t *aes_crypt);
int lega_aes_finalize(lega_aes_dev_t *aes_crypt);
#endif //_LEGA_AES_H_

View file

@ -0,0 +1,80 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*!
@file
@brief This file contains all of the enums and definitions that are used for the
CryptoCell Lib init and finish APIs, as well as the APIs themselves.
*/
#ifndef __SNS_SILIB_H__
#define __SNS_SILIB_H__
#include "ssi_pal_types.h"
#include "crys_rnd.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* definitions for error returns */
typedef enum {
SA_SILIB_RET_OK = 0,
SA_SILIB_RET_EINVAL_CTX_PTR,
SA_SILIB_RET_EINVAL_WORK_BUF_PTR,
SA_SILIB_RET_HAL,
SA_SILIB_RET_PAL,
SA_SILIB_RET_RND_INST_ERR,
SA_SILIB_RET_EINVAL_HW_VERSION, /* Invalid HW version */
SA_SILIB_RET_EINVAL_HW_SIGNATURE, /* Invalid HW signature */
SA_SILIB_RESERVE32B = 0x7FFFFFFFL
} SA_SilibRetCode_t;
#define DX_VERSION_PRODUCT_BIT_SHIFT 0x18UL
#define DX_VERSION_PRODUCT_BIT_SIZE 0x8UL
/*!
@brief This function Perform global initialization of the ARM CryptoCell 3xx runtime library;
it must be called once per ARM CryptoCell for 3xx cold boot cycle.
Among other initializations, this function calls CRYS_RND_Instantiation and CRYS_RND_SetGenerateVectorFunc
to initialize the TRNG and the primary RND context. An initialized RND context is required for calling RND
APIs and asymmetric cryptography key generation and signatures. The primary context returned by this
function can be used as a single global context for all RND needs. Alternatively, other contexts may
be initialized and used with a more limited scope (for specific applications or specific threads).
\note The Mutexes, if used, are initialized by this API. Therefore, unlike the other APIs in the library,
this API is not thread-safe.
@return SA_SILIB_RET_OK on success.
@return A non-zero value in case of failure.
*/
SA_SilibRetCode_t SaSi_LibInit(CRYS_RND_Context_t *rndContext_ptr, /*!< [in/out] Pointer to the RND context buffer,
allocated by the user. The context is used to maintain the RND state as
well as pointers to a function used for random vector generation.
This context must be saved and provided as parameter to any API that
uses the RND module.*/
CRYS_RND_WorkBuff_t *rndWorkBuff_ptr /*!< [in] Scratchpad for the RND module's work. */);
/*!
@brief This function finalize the library operations. It frees the associated resources (mutexes) and call hal and pal terminate functions.
the function also call CRYS_RND_UnInstantiation to clean the rnd context.
@return SA_SILIB_RET_OK on success.
@return A non-zero value in case of failure.
*/
SA_SilibRetCode_t SaSi_LibFini(CRYS_RND_Context_t *rndContext_ptr /*!< [in/out] Pointer to the RND context buffer that was
initialized in SaSi_LibInit.*/);
#ifdef __cplusplus
}
#endif
#endif /*__DX_CCLIB_H__*/

View file

@ -0,0 +1,283 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*! @file
@brief This file contains all of the enums and definitions that are used for the
CryptoCell AES APIs, as well as the APIs themselves.
*/
#ifndef SSI_AES_H
#define SSI_AES_H
#include "ssi_pal_types.h"
#include "ssi_aes_error.h"
#include "ssi_aes_defs.h"
#ifdef __cplusplus
extern "C"
{
#endif
/************************ Defines ******************************/
/************************ Enums ********************************/
/*!
Encrypt or Decrypt operation mode.
*/
typedef enum {
SASI_AES_ENCRYPT = 0, /*!< Encrypt mode. */
SASI_AES_DECRYPT = 1, /*!< Decrypt mode. */
SASI_AES_NUM_OF_ENCRYPT_MODES,
SASI_AES_ENCRYPT_MODE_LAST = 0x7FFFFFFF
}SaSiAesEncryptMode_t;
/*!
AES operation mode.
*/
typedef enum {
SASI_AES_MODE_ECB = 0, /*!< ECB mode. */
SASI_AES_MODE_CBC = 1, /*!< CBC mode. */
SASI_AES_MODE_CBC_MAC = 2, /*!< CBC-MAC mode. */
SASI_AES_MODE_CTR = 3, /*!< CTR mode. */
SASI_AES_MODE_XCBC_MAC = 4, /*!< XCBC-MAC mode. */
SASI_AES_MODE_CMAC = 5, /*!< CMAC mode. */
SASI_AES_MODE_XTS = 6, /*!< XTS mode. */
SASI_AES_MODE_CBC_CTS = 7, /*!< CBC-CTS mode. */
SASI_AES_MODE_OFB = 8, /*!< OFB mode. */
SASI_AES_NUM_OF_OPERATION_MODES,
SASI_AES_OPERATION_MODE_LAST = 0x7FFFFFFF
}SaSiAesOperationMode_t;
/*!
AES padding type.
*/
typedef enum {
SASI_AES_PADDING_NONE = 0, /*!< No padding. */
SASI_AES_PADDING_PKCS7 = 1, /*!< PKCS7 padding. */
SASI_AES_NUM_OF_PADDING_TYPES,
SASI_AES_PADDING_TYPE_LAST = 0x7FFFFFFF
}SaSiAesPaddingType_t;
/*!
AES key type.
*/
typedef enum {
SASI_AES_USER_KEY = 0, /*!< user key. */
SASI_AES_PLATFORM_KEY = 1, /*!< Kplt hardware key. */
SASI_AES_CUSTOMER_KEY = 2, /*!< Kcst hardware key. */
SASI_AES_NUM_OF_KEY_TYPES,
SASI_AES_KEY_TYPE_LAST = 0x7FFFFFFF
}SaSiAesKeyType_t;
/************************ Typedefs ****************************/
/*! Defines the IV buffer - 16 bytes array. */
typedef uint8_t SaSiAesIv_t[SASI_AES_IV_SIZE_IN_BYTES];
/*! Defines the AES key data buffer. */
typedef uint8_t SaSiAesKeyBuffer_t[SASI_AES_KEY_MAX_SIZE_IN_BYTES];
/************************ Structs ******************************/
/*! The user's context prototype - the argument type that is passed by the user
to the APIs called. */
typedef struct SaSiAesUserContext_t {
uint32_t buff[SASI_AES_USER_CTX_SIZE_IN_WORDS]; /*!< Buffer for the AES context. */
}SaSiAesUserContext_t;
/*! AES User Key Data. */
typedef struct SaSiAesUserKeyData_t {
uint8_t * pKey; /*!< Pointer to the key. */
size_t keySize; /*!< The key size in bytes. Valid values:
- For XTS mode - 32 or 64 byte, indicating the full size of the double key (2x128 or 2x256 bit).
- For XCBC-MAC mode - 16 byte (limited by the standard).
- For all other modes - 16, 24 or 32 byte. */
}SaSiAesUserKeyData_t;
/*! AES HW Key Data - this structure is likely to be changed when we'll start using it. */
typedef struct SaSiAesHwKeyData_t {
size_t slotNumber; /*!< Slot number. */
}SaSiAesHwKeyData_t;
/************************ Functions *****************************/
/*!
@brief This function is used to initialize an AES operation context.
To operate the AES machine, this must be the first API called.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesInit(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context buffer that is allocated by the caller and initialized by this API.
Should be used in all subsequent calls that are part of the same operation. */
SaSiAesEncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether an AES Encrypt (SASI_AES_Encrypt) or Decrypt (SASI_AES_Decrypt) operation should be performed.
Must be set to CRYS_AES_Encrypt in CBC-MAC, XCBC-MAC and CMAC modes. */
SaSiAesOperationMode_t operationMode, /*!< [in] The operation cipher/mode. */
SaSiAesPaddingType_t paddingType /*!< [in] The padding type for AES operation:
- NONE - supported for all operation modes.
- PKCS7 - supported for ECB, CBC, CBC-MAC operation modes. */
);
/*!
@brief This function sets the key information for the AES operation, in the context that was initialized by SaSi_AesInit.
\note When FIPS certification mode is set to ON, and the mode is AES-XTS, weak keys are not allowed (128/256 lsb bits must be
different than 128/256 msb bits, according to the key size).
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesSetKey(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context, after it was initialized by SaSi_AesInit. */
SaSiAesKeyType_t keyType, /*!< [in] The type of key to be used for the AES operation.
Currently only SASI_AES_USER_KEY is supported - the key is plaintext and provided in the pKeyData parameter. */
void * pKeyData, /*!< [in] Pointer to the key data structure (to be casted to the relevant struct type). */
size_t keyDataSize /*!< [in] The size of data passed in pKeyData in bytes. */
);
/*!
@brief This function sets the IV, counter or tweak data for the following AES operation on the same context.
The context must be first initialized by SaSi_AesInit.
It must be called at least once prior to the first SaSi_AesBlock operation on the same context - for those ciphers that require it.
If needed, it can also be called to override the IV in the middle of a sequence of SaSi_AesBlock operations.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesSetIv(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */
SaSiAesIv_t pIV /*!< [in] Pointer to the buffer of the IV, counter or tweak.
<ul><li> For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.</li>
<li> For CTR mode - the counter.</li>
<li> For XTS mode - the tweak value.</li>
<li> For all other modes - N/A. </li></ul>*/
);
/*!
@brief This function retrieves the current IV, counter or tweak from the AES context.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesGetIv(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */
SaSiAesIv_t pIV /*!< [out] Pointer to the buffer of the IV, counter or tweak.
<ul><li> For CBC, CBC-CTS, OFB and CBC-MAC modes - the IV value.</li>
<li> For CTR mode - the counter.</li>
<li> For XTS mode - the tweak value.</li>
<li> For all other modes - N/A. </li></ul> */
);
/*!
@brief This function performs an AES operation on an input data buffer, according to the configuration defined in the context parameter.
It can be called as many times as needed, until all the input data is processed.
SaSi_AesInit, SaSi_AesSetKey, and for some ciphers SaSi_AesSetIv, must be called before
the first call to this API with the same context.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesBlock(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */
uint8_t * pDataIn, /*!< [in] Pointer to the buffer of the input data to the AES. The pointer does not need to be aligned.
For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries,
and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB).
For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */
size_t dataInSize, /*!< [in] Size of the input data in bytes.
<ul><li> For all modes except XTS, must be multiple of 16 bytes.</li>
<li> For XTS mode, only the following data sizes are supported: 64, 512, 520, 521, 1024 and 4096 bytes.
The data passed in a single SaSi_AesBlock call is considered to be a single XTS unit.
All subsequent calls to this API with the same context must use the same data size. </li></ul>*/
uint8_t * pDataOut /*!< [out] Pointer to the output buffer. The pointer does not need to be aligned.
For CBC-MAC, XCBC-MAC, CMAC modes it may be NULL.
For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries,
and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB).
For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */
);
/*!
@brief This function is used to finish AES operation.
It processes the last data block if needed, finalizes the AES operation (cipher-specific),
and produces operation results (for MAC operations).
\note In case AES padding is used (PKCS#7) Din and Dout user's buffers must include extra space for
the padding scheme.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesFinish(
SaSiAesUserContext_t * pContext, /*!< [in] Pointer to the AES context. */
size_t dataSize, /*!< [in] The size of the input data in bytes.
<ul><li> For CBC-CTS mode, must be > 16. Can be <=16 only if this is the only data (no previous calls were
made to SaSi_AesBlock with the same context).</li>
<li> For XTS mode, the data size must conform to the dataInSize rules as listed for XTS under the
SaSi_AesBlock API, and match the data size passed in the previous calls to SaSi_AesBlock with the
same context.</li>
<li> For all other modes, zero is a valid size.</li>
<li> For ECB, CBC, CBC-MAC modes: </li>
<ul><li> Must be >= 0, if direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7.</li>
<li> Must be >= 16 and a multiple of 16 bytes, if direction is SASI_AES_DECRYPT and padding type
is SASI_AES_PADDING_PKCS7.</li>
<li> Must be a multiple of 16 bytes, otherwise. </li></ul></ul>*/
uint8_t * pDataIn, /*!< [in] Pointer of the input data buffer.
For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries,
and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB).
For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */
size_t dataInBuffSize, /*!< [in] Size of pDataIn buffer in bytes.
<ul><li> Must be >= dataSize. </li>
<li> According to padding type, must be >= dataSize + padding. For PKCS7, padding size is
maximum SASI_AES_BLOCK_SIZE_IN_BYTES. </li></ul>*/
uint8_t * pDataOut, /*!< [out] Pointer to the output buffer.
For TZ, the size of the scatter/gather list representing the data buffer is limited to 128 entries,
and the size of each entry is limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB).
For ARM CryptoCell 3xx, The buffer must be contiguous and limited to 64KB. */
size_t * dataOutBuffSize /*!< [in,out] In - Size of pDataOut buffer in bytes.
The output buffer size must be no less than:
<ul><li> For CBC-MAC, XCBC-MAC, CMAC modes - 16 bytes (for MAC result).</li>
<li> For non-MAC modes - dataInBuffSize.</li></ul>
Out - The size in bytes of the actual output data:
<ul><li> If direction is SASI_AES_ENCRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the actual size
with the padding.</li>
<li> If direction is SASI_AES_DECRYPT and padding type is SASI_AES_PADDING_PKCS7, it is the size without
the padding. </li>
<li> For CBC-MAC, XCBC-MAC, CMAC modes - always 16 bytes. </li></ul>*/
);
/*!
@brief This function releases and crears resources after AES operations.
@return SASI_OK on success,
@return A non-zero value from ssi_aes_error.h on failure.
*/
CIMPORT_C SaSiError_t SaSi_AesFree(
SaSiAesUserContext_t * pContext /*!< [in] Pointer to the AES context. */
);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef SSI_AES_H */

View file

@ -0,0 +1,51 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*!
@file
@brief This file contains definitions that are used for the ARM CryptoCell 3xx version of the CryptoCell AES APIs.
*/
#ifndef SSI_AES_DEFS_H
#define SSI_AES_DEFS_H
#include "ssi_pal_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
/************************ Defines ******************************/
/*! The size of the user's context prototype (see SaSiAesUserContext_t) in words. */
#define SASI_AES_USER_CTX_SIZE_IN_WORDS (4+4+7+4)
/*! The AES block size in words. */
#define SASI_AES_BLOCK_SIZE_IN_WORDS 4
/*! The AES block size in bytes. */
#define SASI_AES_BLOCK_SIZE_IN_BYTES (SASI_AES_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t))
/*! The size of the IV buffer in words. */
#define SASI_AES_IV_SIZE_IN_WORDS SASI_AES_BLOCK_SIZE_IN_WORDS
/*! The size of the IV buffer in bytes. */
#define SASI_AES_IV_SIZE_IN_BYTES (SASI_AES_IV_SIZE_IN_WORDS * sizeof(uint32_t))
/*! The maximum size of the AES KEY in words. */
#define SASI_AES_KEY_MAX_SIZE_IN_WORDS 4
/*! The maximum size of the AES KEY in bytes. */
#define SASI_AES_KEY_MAX_SIZE_IN_BYTES (SASI_AES_KEY_MAX_SIZE_IN_WORDS * sizeof(uint32_t))
#ifdef __cplusplus
}
#endif
#endif /* #ifndef SSI_AES_DEFS_H */

View file

@ -0,0 +1,75 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*!
@file
@brief This file contains the definitions of the CryptoCell AES errors.
*/
#ifndef SSI_AES_ERROR_H
#define SSI_AES_ERROR_H
#include "crys_error.h"
#ifdef __cplusplus
extern "C"
{
#endif
/************************ Defines ******************************/
/* generic errors */
#define SASI_FATAL_ERROR CRYS_FATAL_ERROR
#define SASI_OUT_OF_RESOURCE_ERROR CRYS_OUT_OF_RESOURCE_ERROR
#define SASI_ILLEGAL_RESOURCE_VAL_ERROR CRYS_ILLEGAL_RESOURCE_VAL_ERROR
/* CRYS_AES_MODULE_ERROR_BASE - 0x00F00000 */
#define SASI_AES_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x00UL)
#define SASI_AES_INVALID_IV_OR_TWEAK_PTR_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x01UL)
#define SASI_AES_ILLEGAL_OPERATION_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x02UL)
#define SASI_AES_ILLEGAL_KEY_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x03UL)
#define SASI_AES_INVALID_KEY_POINTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x04UL)
#define SASI_AES_KEY_TYPE_NOT_SUPPORTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x05UL)
#define SASI_AES_INVALID_ENCRYPT_MODE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x06UL)
#define SASI_AES_USER_CONTEXT_CORRUPTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x07UL)
#define SASI_AES_DATA_IN_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x08UL)
#define SASI_AES_DATA_OUT_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x09UL)
#define SASI_AES_DATA_IN_SIZE_ILLEGAL (CRYS_AES_MODULE_ERROR_BASE + 0x0AUL)
#define SASI_AES_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0BUL)
#define SASI_AES_DATA_IN_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0CUL)
#define SASI_AES_DATA_OUT_BUFFER_SIZE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0DUL)
#define SASI_AES_ILLEGAL_PADDING_TYPE_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0EUL)
#define SASI_AES_INCORRECT_PADDING_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x0FUL)
#define SASI_AES_CORRUPTED_OUTPUT_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x10UL)
#define SASI_AES_DATA_OUT_SIZE_POINTER_INVALID_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x11UL)
#define SASI_AES_DECRYPTION_NOT_ALLOWED_ON_THIS_MODE (CRYS_AES_MODULE_ERROR_BASE + 0x12UL)
#define SASI_AES_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x15UL)
#define SASI_AES_CTX_SIZES_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x16UL)
#define SASI_AES_ILLEGAL_PARAMS_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x60UL)
#define SASI_AES_CTR_ILLEGAL_BLOCK_OFFSET_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x70UL)
#define SASI_AES_CTR_ILLEGAL_COUNTER_ERROR (CRYS_AES_MODULE_ERROR_BASE + 0x71UL)
#define SASI_AES_IS_NOT_SUPPORTED (CRYS_AES_MODULE_ERROR_BASE + 0xFFUL)
/************************ Enums ********************************/
/************************ Typedefs ****************************/
/************************ Structs *****************************/
/************************ Public Variables *********************/
/************************ Public Functions *********************/
#ifdef __cplusplus
}
#endif
#endif /* #ifndef SSI_AES_ERROR_H */

View file

@ -0,0 +1,63 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*!
@file
@brief This file contains the platform dependent definitions and types.
*/
#ifndef SSI_PAL_TYPES_H
#define SSI_PAL_TYPES_H
#include "ssi_pal_types_plat.h"
typedef enum {
SASI_FALSE = 0,
SASI_TRUE = 1
} SaSiBool;
#define SASI_SUCCESS 0UL
#define SASI_FAIL 1UL
#define SASI_1K_SIZE_IN_BYTES 1024
#define SASI_BITS_IN_BYTE 8
#define SASI_BITS_IN_32BIT_WORD 32
#define SASI_32BIT_WORD_SIZE (sizeof(uint32_t))
#define SASI_OK SASI_SUCCESS
#define SASI_UNUSED_PARAM(prm) ((void)prm)
#define SASI_MAX_UINT32_VAL (0xFFFFFFFF)
/* Minimum and Maximum macros */
#ifdef min
#define CRYS_MIN(a,b) min( a , b )
#else
#define CRYS_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) )
#endif
#ifdef max
#define CRYS_MAX(a,b) max( a , b )
#else
#define CRYS_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) )
#endif
#define CALC_FULL_BYTES(numBits) (((numBits) + (SASI_BITS_IN_BYTE -1))/SASI_BITS_IN_BYTE)
#define CALC_FULL_32BIT_WORDS(numBits) (((numBits) + (SASI_BITS_IN_32BIT_WORD -1))/SASI_BITS_IN_32BIT_WORD)
#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) (((sizeBytes) + SASI_32BIT_WORD_SIZE - 1) / SASI_32BIT_WORD_SIZE)
#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits)*SASI_BITS_IN_32BIT_WORD)
#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits)*SASI_BITS_IN_BYTE)
#define ROUNDUP_BYTES_TO_32BIT_WORD(numBytes) (SASI_32BIT_WORD_SIZE*(((numBytes)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE))
#endif

View file

@ -0,0 +1,31 @@
/****************************************************************************
* This confidential and proprietary software may be used only as authorized *
* by a licensing agreement from ARM Israel. *
* Copyright (C) 2015 ARM Limited or its affiliates. All rights reserved. *
* The entire notice above must be reproduced on all authorized copies and *
* copies may only be made to the extent permitted by a licensing agreement *
* from ARM Israel. *
*****************************************************************************/
/*! @file
@brief This file contains basic type definitions that are platform dependent.
*/
#ifndef SSI_PAL_TYPES_PLAT_H
#define SSI_PAL_TYPES_PLAT_H
/* Host specific types for standard (ISO-C99) compilant platforms */
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
typedef uintptr_t SaSiVirtAddr_t;
typedef uint32_t SaSiBool_t;
typedef uint32_t SaSiStatus;
#define SaSiError_t SaSiStatus
#define SASI_INFINITE 0xFFFFFFFF
#define CEXPORT_C
#define CIMPORT_C
#endif /*SSI_PAL_TYPES_PLAT_H*/

View file

@ -0,0 +1,106 @@
#include <stdio.h>
#include "lega_cm4.h"
#include "lega_common.h"
#include "lega_peripheral_reg.h"
#include "sns_silib.h"
#include "crys_rnd.h"
#include "lega_aes.h"
int lega_aes_init(lega_aes_dev_t *aes_crypt)
{
//C310 clock enable
#ifdef LEGA_A0V2
REG_WR(SYS_REG_BASE_C310_CLK, 0x1);
delay(50);
#endif
return SaSi_LibInit((CRYS_RND_Context_t *)aes_crypt->p_workspace, (CRYS_RND_WorkBuff_t *)(aes_crypt->p_workspace + sizeof(CRYS_RND_Context_t)));
}
int lega_aes_crypt(lega_aes_dev_t *aes_crypt)
{
int ret = 0;
uint32_t block_index;
uint8_t *dataInBuff;
uint8_t *dataOutBuff;
SaSiAesUserContext_t ContextID;
SaSiAesUserKeyData_t keyData;
size_t outSize = 0;
/*In case of non Linux platform set data pointers to test's vectors */
dataInBuff = aes_crypt->input_data;
dataOutBuff = aes_crypt->output_data;
/*Call non-integrated APIs - first SaSi_AesInit*/
ret = SaSi_AesInit(&ContextID, aes_crypt->enc_dec_mode, aes_crypt->operation_mode, SASI_AES_PADDING_NONE);
if (ret != SA_SILIB_RET_OK)
{
return ret;
}
if ((aes_crypt->operation_mode == SASI_AES_MODE_CBC)
|| (aes_crypt->operation_mode == SASI_AES_MODE_CTR)
|| (aes_crypt->operation_mode == SASI_AES_MODE_CBC_MAC))
{
ret = SaSi_AesSetIv(&ContextID, aes_crypt->iv_counter);
if (ret != SA_SILIB_RET_OK)
{
return ret;
}
}
keyData.pKey = aes_crypt->key_data;
keyData.keySize = aes_crypt->key_size;
ret = SaSi_AesSetKey(&ContextID, SASI_AES_USER_KEY, &keyData, sizeof(keyData));
if (ret != SA_SILIB_RET_OK)
{
return ret;
}
/*Call CRYS_AES_Block for each 16 byte block data of the input buffer*/
for (block_index = 0; block_index<aes_crypt->data_size/SASI_AES_BLOCK_SIZE_IN_BYTES-1; block_index++)
{
ret = SaSi_AesBlock(&ContextID,
dataInBuff + (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES),
SASI_AES_BLOCK_SIZE_IN_BYTES,
dataOutBuff + (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES));
if (ret != SA_SILIB_RET_OK)
{
return ret;
}
}
outSize = aes_crypt->data_size - (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES);
/*Call CRYS_AES_Finish for the last block (the size may be 0)*/
if (aes_crypt->operation_mode == SASI_AES_MODE_XCBC_MAC ||
aes_crypt->operation_mode == SASI_AES_MODE_CMAC)
{
/*For XCBC_MAC and CMAC modes we should pass to SaSi_AesFinish the begining of the output buffer*/
ret = SaSi_AesFinish(&ContextID,
outSize,
dataInBuff + (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES),
outSize,
dataOutBuff,
&outSize);
}
else
{
/*For the rest of the modes we should pass to SaSi_AesFinish the relevant offset of output buffer*/
ret = SaSi_AesFinish(&ContextID,
outSize,
dataInBuff + (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES),
outSize,
dataOutBuff + (block_index*SASI_AES_BLOCK_SIZE_IN_BYTES),
&outSize);
}
if (ret != SA_SILIB_RET_OK)
{
return ret;
}
return ret;
}
int lega_aes_finalize(lega_aes_dev_t *aes_crypt)
{
return SaSi_LibFini((CRYS_RND_Context_t *)aes_crypt->p_workspace);
}

View file

@ -0,0 +1,19 @@
EXTRA_POST_BUILD_TARGETS += gen_ota_bin
OTA_IMAGE_MODE := "image_compress"
ifeq ($(HOST_OS),Win32)
IMAGE_GEN_HEADER_TOOL := "$($(HOST_MCU_FAMILY)_LOCATION)/tools/image_gen_header/image_gen_header.exe"
else # Win32
ifeq ($(HOST_OS),Linux32)
IMAGE_GEN_HEADER_TOOL := "$($(HOST_MCU_FAMILY)_LOCATION)/tools/image_gen_header/image_gen_header"
else # Linux32
ifeq ($(HOST_OS),Linux64)
IMAGE_GEN_HEADER_TOOL := "$($(HOST_MCU_FAMILY)_LOCATION)/tools/image_gen_header/image_gen_header"
else
$(error not surport for $(HOST_OS))
endif # Linux64
endif # Linux32
endif # Win32
gen_ota_bin:
$(IMAGE_GEN_HEADER_TOOL) $(BIN_OUTPUT_FILE) $(OTA_IMAGE_MODE)

View file

@ -0,0 +1,7 @@
#ifndef _LEGA_HW_H_
#define _LEGA_HW_H_
extern void hal_reboot(void);
extern void hw_start_hal(void);
#endif //_LEGA_HW_H_

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdint.h>
#include "lega_rhino.h"
#include "aos/hal/adc.h"
#include "aos/hal/uart.h"
#include "lega_adc.h"
#include "board.h"
#if defined ADC_ENABLE
/*
typedef struct adc_obj{
uint32_t port;
adc_channel_t channel;
}adc_obj_t;
static adc_obj_t obj[]={
{GPIO4_INDEX, ADC_CHANNEL_NUM0},
{GPIO5_INDEX, ADC_CHANNEL_NUM1},
{GPIO6_INDEX, ADC_CHANNEL_NUM2},
{GPIO7_INDEX, ADC_CHANNEL_NUM3},
{GPIO8_INDEX, ADC_CHANNEL_NUM4},
{GPIO9_INDEX, ADC_CHANNEL_NUM5},
{GPIO10_INDEX, ADC_CHANNEL_NUM6},
{GPIO11_INDEX, ADC_CHANNEL_NUM7},
};
*/
int32_t hal_adc_init(adc_dev_t *adc)
{
return 0;
}
int32_t hal_adc_value_get(adc_dev_t *adc, void *output, uint32_t timeout){
if(adc->port > 8){
*(int32_t*)(output) = -1;
return(-1);
}
*(int32_t*)(output) = lega_adc_get(adc);
return (0);
}
int32_t hal_adc_finalize(adc_dev_t *adc){
return(0);
}
#endif

View file

@ -0,0 +1,156 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_rhino.h"
#include "lega_flash.h"
#include "hal/soc/soc.h"
#include "board.h"
/**
* Get the infomation of the specified flash area
*
* @param[in] in_partition The target flash logical partition
*
* @return HAL_logi_partition struct
*/
hal_logic_partition_t *hal_flash_get_info(hal_partition_t in_partition)
{
hal_logic_partition_t *logic_partition;
logic_partition = (hal_logic_partition_t *)&hal_partitions[ in_partition ];
return logic_partition;
}
/**
* Erase an area on a Flash logical partition
*
* @note Erase on an address will erase all data on a sector that the
* address is belonged to, this function does not save data that
* beyond the address area but in the affected sector, the data
* will be lost.
*
* @param[in] in_partition The target flash logical partition which should be erased
* @param[in] off_set Start address of the erased flash area
* @param[in] size Size of the erased flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_erase(hal_partition_t in_partition, uint32_t off_set, uint32_t size)
{
int32_t ret;
lega_rtos_declare_critical();
lega_rtos_enter_critical();
ret = lega_flash_erase((int)(in_partition), off_set, size);
lega_rtos_exit_critical();
return ret;
}
/**
* Write data to an area on a flash logical partition without erase
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_write(hal_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len)
{
int32_t ret;
lega_rtos_declare_critical();
lega_rtos_enter_critical();
ret = lega_flash_write((int)(in_partition), off_set, in_buf, in_buf_len);
lega_rtos_exit_critical();
return ret;
}
/**
* Write data to an area on a flash logical partition with erase first
*
* @param[in] in_partition The target flash logical partition which should be read which should be written
* @param[in] off_set Point to the start address that the data is written to, and
* point to the last unwritten address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] inBuffer point to the data buffer that will be written to flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_erase_write(hal_partition_t in_partition, uint32_t *off_set,
const void *in_buf, uint32_t in_buf_len)
{
int32_t ret;
lega_rtos_declare_critical();
lega_rtos_enter_critical();
ret = lega_flash_erase_write((int)(in_partition), off_set, in_buf, in_buf_len);
lega_rtos_exit_critical();
return ret;
}
/**
* Read data from an area on a Flash to data buffer in RAM
*
* @param[in] in_partition The target flash logical partition which should be read
* @param[in] off_set Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] outBuffer Point to the data buffer that stores the data read from flash
* @param[in] inBufferLength The length of the buffer
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_read(hal_partition_t in_partition, uint32_t *off_set,
void *out_buf, uint32_t in_buf_len)
{
return lega_flash_read((int)(in_partition), off_set, out_buf, in_buf_len);
}
/**
* Set security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of enabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_enable_secure(hal_partition_t partition, uint32_t off_set, uint32_t size)
{
return lega_flash_enable_secure((int)(partition), off_set, size);
}
/**
* Disable security options on a logical partition
*
* @param[in] partition The target flash logical partition
* @param[in] offset Point to the start address that the data is read, and
* point to the last unread address after this function is
* returned, so you can call this function serval times without
* update this start address.
* @param[in] size Size of disabled flash area
*
* @return 0 : On success, EIO : If an error occurred with any step
*/
int32_t hal_flash_dis_secure(hal_partition_t partition, uint32_t off_set, uint32_t size)
{
return lega_flash_dis_secure((int)(partition), off_set, size);
}

View file

@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_cm4.h"
#include "lega_gpio.h"
#include "hal/soc/soc.h"
/**
* Initialises a GPIO pin
*
* @note Prepares a GPIO pin for use.
*
* @param[in] gpio the gpio pin which should be initialised
* @param[in] configuration A structure containing the required gpio configuration
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_init(gpio_dev_t *gpio)
{
return lega_gpio_init((lega_gpio_dev_t *)gpio);
}
/**
* Sets an output GPIO pin high
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set high
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_output_high(gpio_dev_t *gpio)
{
return lega_gpio_output_high((lega_gpio_dev_t *)gpio);
}
/**
* Sets an output GPIO pin low
*
* @note Using this function on a gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_output_low(gpio_dev_t *gpio)
{
return lega_gpio_output_low((lega_gpio_dev_t *)gpio);
}
/**
* Trigger an output GPIO pin's output. Using this function on a
* gpio pin which is set to input mode is undefined.
*
* @param[in] gpio the gpio pin which should be set low
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_output_toggle(gpio_dev_t *gpio)
{
return lega_gpio_output_toggle((lega_gpio_dev_t *)gpio);
}
/**
* Get the state of an input GPIO pin. Using this function on a
* gpio pin which is set to output mode will return an undefined value.
*
* @param[in] gpio the gpio pin which should be read
* @param[in] value gpio value
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_input_get(gpio_dev_t *gpio, uint32_t *value)
{
return lega_gpio_input_get((lega_gpio_dev_t *)gpio, value);
}
/**
* Enables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which is set to
* output mode is undefined.
*
* @param[in] gpio the gpio pin which will provide the interrupt trigger
* @param[in] trigger the type of trigger (rising/falling edge)
* @param[in] handler a function pointer to the interrupt handler
* @param[in] arg an argument that will be passed to the interrupt handler
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger,
gpio_irq_handler_t handler, void *arg)
{
return lega_gpio_enable_irq((lega_gpio_dev_t *)gpio, trigger, handler, arg);
}
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref hal_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_disable_irq(gpio_dev_t *gpio)
{
return lega_gpio_disable_irq((lega_gpio_dev_t *)gpio);
}
/**
* Disables an interrupt trigger for an input GPIO pin.
* Using this function on a gpio pin which has not been set up
* using @ref hal_gpio_input_irq_enable is undefined.
*
* @param[in] gpio the gpio pin which provided the interrupt trigger
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_clear_irq(gpio_dev_t *gpio)
{
return lega_gpio_clear_irq((lega_gpio_dev_t *)gpio);
}
/**
* Set a GPIO pin in default state.
*
* @param[in] gpio the gpio pin which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_gpio_finalize(gpio_dev_t *gpio)
{
return lega_gpio_finalize((lega_gpio_dev_t *)gpio);
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include "lega_cm4.h"
#include <hw.h>
#include "board.h"
void hal_reboot(void)
{
lega_system_reset();
}
void hw_start_hal(void)
{
printf("start-----------hal\n");
}

View file

@ -0,0 +1,227 @@
#include <stdio.h>
#include <stdint.h>
#include "soc.h"
#include "lega_cm4.h"
#include "lega_rhino.h"
#include "lega_i2c.h"
#include "i2c.h"
lega_semaphore_t g_lega_i2c_sem[LEGA_I2C_NUM];
lega_queue_t g_lega_i2c_queue[LEGA_I2C_NUM];
char *g_lega_i2c_queue_name[LEGA_I2C_NUM] =
{
"lega_i2c0_queue",
"lega_i2c1_queue"
};
void hal_i2c0_slv_tx_callback(void)
{
lega_rtos_set_semaphore(&g_lega_i2c_sem[I2C_DEVICE0]);
}
void hal_i2c0_slv_rx_callback(uint8_t data)
{
lega_rtos_push_to_queue(&g_lega_i2c_queue[I2C_DEVICE0],&data,LEGA_NEVER_TIMEOUT);
}
void hal_i2c1_slv_tx_callback(void)
{
lega_rtos_set_semaphore(&g_lega_i2c_sem[I2C_DEVICE1]);
}
void hal_i2c1_slv_rx_callback(uint8_t data)
{
lega_rtos_push_to_queue(&g_lega_i2c_queue[I2C_DEVICE1],&data,LEGA_NEVER_TIMEOUT);
}
/**
* Initialises an I2C interface
* Prepares an I2C hardware interface for communication as a master or slave
*
* @param[in] i2c the device for which the i2c port should be initialised
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_init(i2c_dev_t *i2c)
{
int32_t ret;
ret = lega_i2c_init((lega_i2c_dev_t *)i2c);
if(!ret && (I2C_MODE_SLAVE == i2c->config.mode))
{
ret = lega_rtos_init_semaphore(&g_lega_i2c_sem[i2c->port], 0);
if(!ret)
{
ret = lega_rtos_init_queue(&g_lega_i2c_queue[i2c->port],g_lega_i2c_queue_name[i2c->port],1,I2C_BUF_QUEUE_SIZE);
}
}
return ret;
}
/**
* I2c master send
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] data i2c send data
* @param[in] size i2c send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_master_send(i2c_dev_t *i2c, uint16_t dev_addr, const uint8_t *data,
uint16_t size, uint32_t timeout)
{
return lega_i2c_master_send((lega_i2c_dev_t *)i2c, dev_addr, data, size, timeout);
}
/**
* I2c master recv
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[out] data i2c receive data
* @param[in] size i2c receive data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_master_recv(i2c_dev_t *i2c, uint16_t dev_addr, uint8_t *data,
uint16_t size, uint32_t timeout)
{
return lega_i2c_master_recv((lega_i2c_dev_t *)i2c, dev_addr, data, size, timeout);
}
/**
* I2c slave send
*
* @param[in] i2c the i2c device
* @param[in] data i2c slave send data
* @param[in] size i2c slave send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_slave_send(i2c_dev_t *i2c, const uint8_t *data, uint16_t size, uint32_t timeout)
{
uint16_t i = 0;
int32_t ret;
if((NULL == i2c) || (NULL == data) || (0 == size))
{
return -1;
}
if(HAL_WAIT_FOREVER == timeout)
{
timeout = LEGA_NEVER_TIMEOUT;
}
while(i < size)
{
if(!lega_rtos_get_semaphore(&g_lega_i2c_sem[i2c->port], timeout))
{
ret = lega_i2c_tx_data((lega_i2c_dev_t *)i2c, data[i++]);
if(ret)
{
return ret;
}
}
}
return 0;
}
/**
* I2c slave receive
*
* @param[in] i2c tthe i2c device
* @param[out] data i2c slave receive data
* @param[in] size i2c slave receive data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_slave_recv(i2c_dev_t *i2c, uint8_t *data, uint16_t size, uint32_t timeout)
{
uint16_t i = 0;
int32_t ret;
if((NULL == i2c) || (NULL == data))
{
return -1;
}
if(i2c->port >= LEGA_I2C_NUM)
{
return -1;
}
if(HAL_WAIT_FOREVER == timeout)
{
timeout = LEGA_NEVER_TIMEOUT;
}
while(i < size)
{
ret = lega_rtos_pop_from_queue(&g_lega_i2c_queue[i2c->port],(data+i++),timeout);
if(ret)
{
return ret;
}
}
return 0;
}
/**
* I2c mem write
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[in] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_mem_write(i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, const uint8_t *data, uint16_t size,
uint32_t timeout)
{
return lega_i2c_mem_write((lega_i2c_dev_t *)i2c, dev_addr, mem_addr, mem_addr_size, data, size, timeout);
}
/**
* I2c master mem read
*
* @param[in] i2c the i2c device
* @param[in] dev_addr device address
* @param[in] mem_addr mem address
* @param[in] mem_addr_size mem address
* @param[out] data i2c master send data
* @param[in] size i2c master send data size
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred during initialisation
*/
int32_t hal_i2c_mem_read(i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
uint16_t mem_addr_size, uint8_t *data, uint16_t size,
uint32_t timeout)
{
return lega_i2c_mem_read((lega_i2c_dev_t *)i2c, dev_addr, mem_addr, mem_addr_size, data, size, timeout);
}
/**
* Deinitialises an I2C device
*
* @param[in] i2c the i2c device
*
* @return 0 : on success, EIO : if an error occurred during deinitialisation
*/
int32_t hal_i2c_finalize(i2c_dev_t *i2c)
{
return lega_i2c_finalize((lega_i2c_dev_t *)i2c);
}

View file

@ -0,0 +1,242 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "aos/kernel.h"
#include "aos/kv.h"
#include "hal/soc/flash.h"
#include "ota_hal_plat.h"
#include "ota_hal_os.h"
#include "ota_log.h"
#define OTA_CRC16 "ota_file_crc16"
static unsigned int _offset = 0;
#define TMP_BUF_LEN 1024
int ota_image_check(uint32_t image_size)
{
uint32_t filelen, flashaddr, len = 0, left;
uint8_t md5_recv[16];
uint8_t md5_calc[16];
ota_md5_context ctx;
uint8_t *tmpbuf;
tmpbuf = (uint8_t *)malloc(TMP_BUF_LEN);
filelen = image_size - 16;
flashaddr = filelen;
hal_flash_read(HAL_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)md5_recv, 16);
ota_md5_init(&ctx);
ota_md5_starts(&ctx);
flashaddr = 0;
left = filelen;
while (left > 0)
{
if (left > TMP_BUF_LEN)
{
len = TMP_BUF_LEN;
}
else
{
len = left;
}
left -= len;
hal_flash_read(HAL_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)tmpbuf, len);
ota_md5_update(&ctx, (uint8_t *)tmpbuf, len);
}
ota_md5_finish(&ctx, md5_calc);
ota_md5_free(&ctx);
if (memcmp(md5_calc, md5_recv, 16) != 0)
{
OTA_LOG_I("RX: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
md5_recv[0], md5_recv[1], md5_recv[2], md5_recv[3],
md5_recv[4], md5_recv[5], md5_recv[6], md5_recv[7],
md5_recv[8], md5_recv[9], md5_recv[10], md5_recv[11],
md5_recv[12], md5_recv[13], md5_recv[14], md5_recv[15]);
OTA_LOG_I("Need: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
md5_calc[0], md5_calc[1], md5_calc[2], md5_calc[3],
md5_calc[4], md5_calc[5], md5_calc[6], md5_calc[7],
md5_calc[8], md5_calc[9], md5_calc[10], md5_calc[11],
md5_calc[12], md5_calc[13], md5_calc[14], md5_calc[15]);
OTA_LOG_I("user crc check fail\r\n");
goto exit;
}
OTA_LOG_I("OTA image md5 check success");
return 0;
exit:
return -1;
}
int ota_image_crc(uint32_t image_size)
{
uint16_t crcout;
uint32_t filelen, flashaddr, len = 0, left;
ota_crc16_ctx ctx = {0};
uint8_t *tmpbuf;
tmpbuf = (uint8_t *)malloc(TMP_BUF_LEN);
filelen = image_size - 16;
ota_crc16_init(&ctx);
flashaddr = 0;
left = filelen;
while (left > 0)
{
if (left > TMP_BUF_LEN)
{
len = TMP_BUF_LEN;
}
else
{
len = left;
}
left -= len;
hal_flash_read(HAL_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)tmpbuf, len);
ota_crc16_update(&ctx, tmpbuf, len);
}
ota_crc16_final(&ctx, &crcout);
return crcout;
}
static int ota_init(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
_offset = param->off_bp;
hal_logic_partition_t *part_info = hal_flash_get_info(HAL_PARTITION_OTA_TEMP);
OTA_LOG_I("ota init off:0x%08x part:%d len:0x%08x\n", param->off_bp, HAL_PARTITION_OTA_TEMP, param->len);
if (part_info->partition_length < param->len || param->len == 0)
{
ret = OTA_PARAM_FAIL;
return ret;
}
if (param->off_bp == 0)
{
int ret = 0;
int len = part_info->partition_length;
int offset = _offset;
while (len > 0)
{
ret = hal_flash_erase(HAL_PARTITION_OTA_TEMP, offset, 4096);
if (ret != 0)
{
ret = OTA_INIT_FAIL;
return ret;
}
offset += 4096;
len -= 4096;
aos_msleep(1);
}
}
OTA_LOG_I("ota erase completed\r\n");
return ret;
}
static int ota_write(int *off, char *in_buf, int in_buf_len)
{
return hal_flash_write(HAL_PARTITION_OTA_TEMP, (uint32_t *)&_offset, (uint8_t *)in_buf, in_buf_len);
}
static int ota_read(int *off, char *out_buf, int out_buf_len)
{
return hal_flash_read(HAL_PARTITION_OTA_TEMP, (uint32_t *)off, (uint8_t *)out_buf, out_buf_len);
}
typedef struct
{
uint32_t dst_adr;
uint32_t src_adr;
uint32_t siz;
uint16_t crc;
} ota_hdr_t;
static int hal_ota_switch(uint32_t ota_len, uint16_t ota_crc)
{
uint32_t addr = 0;
ota_hdr_t ota_hdr = {
.dst_adr = 0xA000,
.src_adr = 0x100000,
.siz = ota_len,
.crc = ota_crc,
};
hal_flash_write(HAL_PARTITION_PARAMETER_1, &addr, (uint8_t *)&ota_hdr, sizeof(ota_hdr));
return 0;
}
static int ota_boot(void *something)
{
int ret = 0;
ota_boot_param_t *param = (ota_boot_param_t *)something;
if (param == NULL)
{
ret = OTA_REBOOT_FAIL;
return ret;
}
if (param->res_type == OTA_FINISH)
{
if (param->upg_flag == OTA_DIFF)
{
}
else
{
if (ota_image_check(param->len) != 0)
{
return -1;
}
param->crc = ota_image_crc(param->len);
OTA_LOG_I("ota finished, switch to new firmware ...");
hal_ota_switch(param->len - 16, param->crc);
}
ota_reboot();
}
return ret;
}
static int ota_rollback(void *something)
{
return 0;
}
const char *aos_get_app_version(void);
static const char *ota_get_version(unsigned char dev_type)
{
if (dev_type)
{
return "v1.0.0-20180101-1000"; //SYSINFO_APP_VERSION;
}
else
{
return aos_get_app_version();
}
}
ota_hal_module_t ota_hal_module = {
.init = ota_init,
.write = ota_write,
.read = ota_read,
.boot = ota_boot,
.rollback = ota_rollback,
.version = ota_get_version,
};

View file

@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_cm4.h"
#include "lega_pwm.h"
#include "hal/soc/pwm.h"
/**
* Initialises a PWM pin
*
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_pwm_init(pwm_dev_t *pwm)
{
return lega_pwm_init((lega_pwm_dev_t *)pwm);
}
/**
* Starts Pulse-Width Modulation signal output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_pwm_start(pwm_dev_t *pwm)
{
return lega_pwm_start((lega_pwm_dev_t *)pwm);
}
/**
* Stops output on a PWM pin
*
* @param[in] pwm the PWM device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_pwm_stop(pwm_dev_t *pwm)
{
return lega_pwm_stop((lega_pwm_dev_t *)pwm);
}
/**
* change the para of pwm
*
* @param[in] pwm the PWM device
* @param[in] para the para of pwm
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_pwm_para_chg(pwm_dev_t *pwm, pwm_config_t para)
{
lega_pwm_config_t lega_para;
lega_para.duty_cycle = para.duty_cycle;
lega_para.freq = para.freq;
return lega_pwm_para_chg((lega_pwm_dev_t *)pwm, lega_para);
}
/**
* De-initialises an PWM interface, Turns off an PWM hardware interface
*
* @param[in] pwm the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_pwm_finalize(pwm_dev_t *pwm)
{
return lega_pwm_finalize((lega_pwm_dev_t *)pwm);
}

View file

@ -0,0 +1,158 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
DESCRIPTION
This library provides the support for the STM32L496G-DISCOVERY
CPU power state control.
CPU power management:
provides low-level interface for setting CPU C-states.
provides low-level interface for setting CPU P-states.
*/
#include <k_api.h>
#if (AOS_COMP_PWRMGMT > 0)
#include <cpu_pwr.h>
#include <cpu_pwr_hal_lib.h>
#include <pwrmgmt_debug.h>
#include <cpu_tickless.h>
#include <pmu.h>
/* forward declarations */
extern one_shot_timer_t rtc_one_shot; /* wakeup source for C3,C4 */
static cpu_pwr_t cpu_pwr_node_core_0;
uint32_t cpu_pwr_minisleep_time_ms = 0;
/**
* board_cpu_c_state_set - program CPU into Cx idle state
*
* RUN Context: could be called from ISR context or task context.
*
* SMP Consider: STM32L496G-DISCOVERY do not support SMP, so only UP is enough.
*
* @return PWR_OK or PWR_ERR when failed.
*/
static pwr_status_t board_cpu_c_state_set(uint32_t cpuCState, int master)
{
switch (cpuCState) {
case CPU_CSTATE_C0:
if (master) {
/*
* do something needed when CPU waked up from C1 or higher
* Cx state.
*/
}
break;
case CPU_CSTATE_C1:
/* put CPU into C1 state, for ARM we can call WFI instruction
to put CPU into C1 state. */
PWR_DBG(DBG_DBG, "enter C1\n");
lega_drv_goto_sleep(PMU_STATE_MODEMSLEEP);
__WFI__();
PWR_DBG(DBG_DBG, "exit C1\n");
break;
default:
PWR_DBG(DBG_ERR, "invalid C state: C%d\n", cpuCState);
break;
}
return PWR_OK;
}
/**
* board_cpu_pwr_init() is called by HAL lib to
* init board powr manage configure.
*
* RUN Context: could be called from task context only, ISR context is not
* supported.
*
* SMP Consider: STM32L496G-DISCOVERY do not support SMP, so only UP is enough.
*
* @return PWR_OK or PWR_ERR when failed.
*/
pwr_status_t board_cpu_pwr_init(void)
{
cpu_pwr_t *pCpuNode = NULL;
pwr_status_t retVal = PWR_OK;
uint32_t cpuIndex = 0; /* 0 for UP */
pCpuNode = &cpu_pwr_node_core_0;
retVal = cpu_pwr_node_init_static("core", 0, pCpuNode);
if (retVal != PWR_OK) {
return PWR_ERR;
}
/* record this node */
retVal = cpu_pwr_node_record(pCpuNode, cpuIndex);
if (retVal == PWR_ERR) {
return PWR_ERR;
}
/*
* According reference manual of STM32L496G-DISCOVERY
*
* C0 - RUN, Power supplies are on,all clocks are on.
* C1 - Sleep mode, CPU clock off, all peripherals including
* Cortex®-M4 core peripherals such as NVIC, SysTick, etc. can run
* and wake up the CPU when an interrupt or an event occurs.
*/
retVal = cpu_pwr_c_method_set(cpuIndex, board_cpu_c_state_set);
if (retVal == PWR_ERR) {
return PWR_ERR;
}
/* save support C status bitset : C0,C1 */
cpu_pwr_c_state_capability_set(cpuIndex, CPU_STATE_BIT(CPU_CSTATE_C0)
| CPU_STATE_BIT(CPU_CSTATE_C1)
);
if (retVal == PWR_ERR) {
return PWR_ERR;
}
/*
* According reference manual of STM32L496G-DISCOVERY,
* the wakeup latency of Cx is:
* resume from C1 (Low Power mode) : immediate
*/
cpu_pwr_c_state_latency_save(cpuIndex, CPU_CSTATE_C0, 0);
cpu_pwr_c_state_latency_save(cpuIndex, CPU_CSTATE_C1, 0);
tickless_one_shot_timer_save(CPU_CSTATE_C1, &rtc_one_shot);
/*
Tell the CPU PWR MGMT module which C state is supported with
tickless function through tickless_c_states_add(c_state_x).
*/
tickless_c_states_add(CPU_STATE_BIT(CPU_CSTATE_C0)
| CPU_STATE_BIT(CPU_CSTATE_C1)
);
#if RHINO_CONFIG_CPU_PWR_SHOW
cpu_pwr_info_show();
cpu_pwr_state_show();
#endif
return retVal;
}
int pwrmgmt_cpu_minisleep_msec_set(uint32_t time_ms)
{
printf("set the minimum sleep time %dms\r\n", time_ms);
cpu_pwr_minisleep_time_ms = time_ms;
return 0;
}
#endif /* AOS_COMP_PWRMGMT */

View file

@ -0,0 +1,82 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
* This file supplied RTC one-shot start/stop services for CPU tickless
* module, verifyied on STM32L496-DISCOVERY with C3/C4 mode.
* C3: stop mode.
* C4: standby mode.
*/
#include <k_api.h>
#if (AOS_COMP_PWRMGMT > 0)
#include <stdint.h>
#include <stdbool.h>
#include <cpu_tickless.h>
#include <pmu.h>
#define RTC_FREQ (32768)
extern uint32_t cpu_pwr_minisleep_time_ms;
static pwr_status_t rtc_init(void);
static uint32_t rtc_one_shot_max_seconds(void);
static pwr_status_t rtc_one_shot_start(uint64_t planUs);
static pwr_status_t rtc_one_shot_stop(uint64_t *pPassedUs);
one_shot_timer_t rtc_one_shot = {
rtc_init,
rtc_one_shot_max_seconds,
rtc_one_shot_start,
rtc_one_shot_stop,
};
static pwr_status_t rtc_init(void)
{
return PWR_OK;
}
static pwr_status_t rtc_one_shot_start(uint64_t planUs)
{
uint32_t status = 0;
uint32_t cc_counter = planUs * RTC_FREQ / 1000000;
if ((planUs / 1000) <= cpu_pwr_minisleep_time_ms) {
planUs = cpu_pwr_minisleep_time_ms * 1000;
cc_counter = planUs * RTC_FREQ / 1000000;
if (cc_counter > lega_drv_rtc_max_ticks_get()) {
cc_counter = lega_drv_rtc_max_ticks_get();
}
}
if ((planUs / 1000) < 4) {
return PWR_ERR;
}
status = lega_drv_rtc_cc_set(cc_counter, PMU_STATE_MODEMSLEEP);
if (status == 0) {
lega_drv_rtc_enable();
return PWR_OK;
} else {
return PWR_ERR;
}
}
static pwr_status_t rtc_one_shot_stop(uint64_t *pPassedUs)
{
uint32_t counter = 0;
counter = lega_drv_rtc_counter_get();
*pPassedUs = (uint64_t)counter * 1000000 / RTC_FREQ;
lega_drv_goto_active();
return PWR_OK;
}
static uint32_t rtc_one_shot_max_seconds(void)
{
return (lega_drv_rtc_max_ticks_get() / RTC_FREQ);
}
#endif /* AOS_COMP_PWRMGMT */

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2018 Alibaba Group Holding Limited
*/
/*
DESCRIPTION
This file provides two fundtions systick_suspend()/systick_resume()
which is used by cpu tickless module to suspend/resume system tick
interrupt.
Differrent board may has different way to suspend/resume system tick
interrupt, please reference your board/soc user manual to find the
detail for how to implement these two functions.
*/
#include <k_api.h>
#if (AOS_COMP_PWRMGMT > 0)
#include "lega_cm4.h"
void systick_suspend(void)
{
SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
}
void systick_resume(void)
{
SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
}
#endif /* AOS_COMP_PWRMGMT */

View file

@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_cm4.h"
#include "lega_rtc.h"
#include "rtc.h"
/**
* This function will initialize the on board CPU real time clock
*
*
* @param[in] rtc rtc device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_rtc_init(rtc_dev_t *rtc)
{
return lega_rtc_init((lega_rtc_dev_t *)rtc);
}
/**
* This function will return the value of time read from the on board CPU real time clock.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_rtc_get_time(rtc_dev_t *rtc, rtc_time_t *time)
{
return lega_rtc_get_time((lega_rtc_dev_t *)rtc, (lega_rtc_time_t *)time);
}
/**
* This function will set MCU RTC time to a new value.
*
* @param[in] rtc rtc device
* @param[out] time pointer to a time structure
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_rtc_set_time(rtc_dev_t *rtc, const rtc_time_t *time)
{
return lega_rtc_set_time((lega_rtc_dev_t *)rtc, (lega_rtc_time_t *)time);
}
/**
* De-initialises an RTC interface, Turns off an RTC hardware interface
*
* @param[in] RTC the interface which should be de-initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_rtc_finalize(rtc_dev_t *rtc)
{
return lega_rtc_finalize((lega_rtc_dev_t *)rtc);
}

View file

@ -0,0 +1,53 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_cm4.h"
#include "lega_timer.h"
#include "hal/soc/timer.h"
/**
* init a hardware timer
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_timer_init(timer_dev_t *tim)
{
return lega_timer_init((lega_timer_dev_t *)tim);
}
/**
* start a hardware timer
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_timer_start(timer_dev_t *tim)
{
return lega_timer_start((lega_timer_dev_t *)tim);
}
/**
* stop a hardware timer
*
* @param[in] tim timer device
*
* @return none
*/
void hal_timer_stop(timer_dev_t *tim)
{
return lega_timer_stop((lega_timer_dev_t *)tim);
}
/**
* De-initialises an TIMER interface, Turns off an TIMER hardware interface
*
* @param[in] tim timer device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_timer_finalize(timer_dev_t *tim)
{
return lega_timer_finalize((lega_timer_dev_t *)tim);
}

View file

@ -0,0 +1,230 @@
#include <stdint.h>
#include "lega_rhino.h"
#include "lega_uart.h"
#include "hal/soc/uart.h"
#include "board.h"
#define HAL_UART_BUF_QUEUE_BYTES 128
lega_queue_t hal_uart_buf_queue[LEGA_UART_NUM];
char * hal_uart_buf_queue_name[LEGA_UART_NUM] =
{
"uart0_buffer_queue",
"uart1_buffer_queue",
"uart2_buffer_queue"
};
void hal_uart0_callback_handler(char ch)
{
lega_rtos_push_to_queue(&hal_uart_buf_queue[LEGA_UART0_INDEX], &ch, LEGA_NEVER_TIMEOUT);
}
void hal_uart1_callback_handler(char ch)
{
lega_rtos_push_to_queue(&hal_uart_buf_queue[LEGA_UART1_INDEX], &ch, LEGA_NEVER_TIMEOUT);
}
void hal_uart2_callback_handler(char ch)
{
lega_rtos_push_to_queue(&hal_uart_buf_queue[LEGA_UART2_INDEX], &ch, LEGA_NEVER_TIMEOUT);
}
/**
* Initialises a UART interface
*
*
* @param[in] uart the interface which should be initialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_uart_init(uart_dev_t *uart)
{
int32_t ret = 0;
if(NULL == uart){
return -1;
}
/*logic port to physical port*/
if(uart->port == PORT_UART_STD){
uart->port = LEGA_UART1_INDEX;
uart->priv = (void *)(hal_uart1_callback_handler);
}
else if(uart->port == PORT_UART_TEMP){
uart->port = LEGA_UART0_INDEX;
}
ret = lega_uart_init((lega_uart_dev_t *)uart);
if((!ret)&&(hal_uart_buf_queue[uart->port] == NULL))
{
ret = lega_rtos_init_queue(&hal_uart_buf_queue[uart->port], hal_uart_buf_queue_name[uart->port], sizeof(char), HAL_UART_BUF_QUEUE_BYTES);
}
return ret;
}
/**
* Transmit data on a UART interface
*
* @param[in] uart the UART interface
* @param[in] data pointer to the start of data
* @param[in] size number of bytes to transmit
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
{
if(NULL == uart){
return -1;
}
/*logic port to physical port*/
if(uart->port == PORT_UART_STD){
uart->port = LEGA_UART1_INDEX;
uart->priv = (void *)(hal_uart1_callback_handler);
}
else if(uart->port == PORT_UART_TEMP){
uart->port = LEGA_UART0_INDEX;
}
return lega_uart_send((lega_uart_dev_t *)uart, data, size, timeout);
}
/**
* Receive data on a UART interface
*
* @param[in] uart the UART interface
* @param[out] data pointer to the buffer which will store incoming data
* @param[in] expect_size number of bytes to receive
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_uart_recv(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t timeout)
{
int i = 0;
int32_t ret;
uint8_t *pdata = (uint8_t *)data;
if((uart == NULL) || (data == NULL))
{
return -1;
}
/*logic port to physical port*/
if(uart->port == PORT_UART_STD){
uart->port = LEGA_UART1_INDEX;
uart->priv = (void *)(hal_uart1_callback_handler);
}
else if(uart->port == PORT_UART_TEMP){
uart->port = LEGA_UART0_INDEX;
}
for (i = 0; i < expect_size; i++)
{
ret = lega_rtos_pop_from_queue(&hal_uart_buf_queue[uart->port], &pdata[i], timeout);
if(ret)
{
return ret;
}
}
return 0;
}
/**
* Receive data on a UART interface
*
* @param[in] uart the UART interface
* @param[out] data pointer to the buffer which will store incoming data
* @param[in] expect_size number of bytes to receive
* @param[out] recv_size number of bytes received
* @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
* if you want to wait forever
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_uart_recv_II(uart_dev_t *uart, void *data, uint32_t expect_size,
uint32_t *recv_size, uint32_t timeout)
{
uint8_t *pdata = (uint8_t *)data;
int i = 0;
uint32_t rx_count = 0;
int32_t ret;
if((uart == NULL) || (data == NULL))
{
return -1;
}
/*logic port to physical port*/
if(uart->port == PORT_UART_STD){
uart->port = LEGA_UART1_INDEX;
uart->priv = (void *)(hal_uart1_callback_handler);
}
else if(uart->port == PORT_UART_TEMP){
uart->port = LEGA_UART0_INDEX;
}
for (i = 0; i < expect_size; i++)
{
ret = lega_rtos_pop_from_queue(&hal_uart_buf_queue[uart->port], &pdata[i], timeout);
if(!ret)
{
rx_count++;
}
else
{
*recv_size = rx_count;
return ret;
}
}
if(recv_size)
{
*recv_size = rx_count;
}
if(rx_count != 0)
{
return 0;
}
else
{
return -1;
}
}
/**
* Deinitialises a UART interface
*
* @param[in] uart the interface which should be deinitialised
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_uart_finalize(uart_dev_t *uart)
{
int32_t ret;
if(NULL == uart){
return -1;
}
/*logic port to physical port*/
if(uart->port == PORT_UART_STD){
uart->port = LEGA_UART1_INDEX;
uart->priv = (void *)(hal_uart1_callback_handler);
}
else if(uart->port == PORT_UART_TEMP){
uart->port = LEGA_UART0_INDEX;
}
ret = lega_rtos_deinit_queue(&hal_uart_buf_queue[uart->port]);
if(!ret)
{
return lega_uart_finalize((lega_uart_dev_t *)uart);
}
else
{
return ret;
}
}

View file

@ -0,0 +1,40 @@
#include <stdio.h>
#include <stdint.h>
#include "lega_cm4.h"
#include "lega_wdg.h"
#include "hal/soc/wdg.h"
/**
* This function will initialize the on board CPU hardware watch dog
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_wdg_init(wdg_dev_t *wdg)
{
return lega_wdg_init((lega_wdg_dev_t *)wdg);
}
/**
* Reload watchdog counter.
*
* @param[in] wdg the watch dog device
*/
void hal_wdg_reload(wdg_dev_t *wdg)
{
return lega_wdg_reload((lega_wdg_dev_t *)wdg);
}
/**
* This function performs any platform-specific cleanup needed for hardware watch dog.
*
* @param[in] wdg the watch dog device
*
* @return 0 : on success, EIO : if an error occurred with any step
*/
int32_t hal_wdg_finalize(wdg_dev_t *wdg)
{
return lega_wdg_finalize((lega_wdg_dev_t *)wdg);
}

View file

@ -0,0 +1,491 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hal/base.h>
#include <hal/wifi.h>
#include "lega_rhino.h"
#include "lega_wlan_api.h"
#include "lega_wlan_api_aos.h"
#include <k_api.h>
hal_wifi_module_t sim_aos_wifi_lega;
monitor_data_cb_t aos_monitor_cb = NULL;
monitor_data_cb_t aos_mgmt_monitor_cb = NULL;
static int wifi_init(hal_wifi_module_t *m)
{
return lega_wlan_init();
}
static void wifi_get_mac_addr(hal_wifi_module_t *m, uint8_t *mac)
{
lega_wlan_get_mac_address(mac);
}
static void wifi_set_mac_addr(hal_wifi_module_t *m, const uint8_t *mac)
{
lega_wlan_set_mac_address(mac);
}
extern uint8_t user_pmk[32];
static int wifi_start(hal_wifi_module_t *m, hal_wifi_init_type_t *init_para)
{
int ret;
lega_wlan_init_type_t conf;
memset(&conf,0,sizeof(lega_wlan_init_type_t));
if (init_para->wifi_mode == STATION)
{
memset(user_pmk, 0, sizeof(user_pmk));
}
conf.dhcp_mode = init_para->dhcp_mode;
conf.wifi_mode = init_para->wifi_mode;
memcpy(conf.wifi_ssid, init_para->wifi_ssid, 32);
memcpy(conf.wifi_key, init_para->wifi_key, 64);
memcpy(conf.local_ip_addr, init_para->local_ip_addr, 16);
memcpy(conf.net_mask, init_para->net_mask, 16);
memcpy(conf.gateway_ip_addr, init_para->gateway_ip_addr, 16);
memcpy(conf.dns_server_ip_addr, init_para->dns_server_ip_addr, 16);
memcpy(conf.reserved, init_para->reserved, 32);
conf.wifi_retry_interval = init_para->wifi_retry_interval;
ret = lega_wlan_open(&conf);
return ret;
}
static int wifi_start_ap(hal_wifi_module_t *m, const char *ssid, const char *passwd, int interval, int hide)
{
int ret;
lega_wlan_init_type_t conf;
memset(&conf, 0, sizeof(lega_wlan_init_type_t));
conf.wifi_mode = SOFT_AP;
printf("wifi_start_ap [%s %s %d]\r\n", ssid,passwd,strlen(passwd));
memcpy(conf.wifi_ssid, ssid, strlen(ssid));
memcpy(conf.wifi_key, passwd, strlen(passwd));
conf.interval = interval;
conf.hide = hide;
ret = lega_wlan_open(&conf);
return ret;
}
static int wifi_stop_ap(hal_wifi_module_t *m)
{
return lega_wlan_close();
}
void wlan_start_adv_cb(lega_start_adv_results_e status)
{
printf("connect_adv status:%d\n", status);
}
static int wifi_start_adv(hal_wifi_module_t *m, hal_wifi_init_type_adv_t *init_para_adv)
{
int ret = -1;
lega_wlan_init_type_t conf;
memset(&conf, 0, sizeof(lega_wlan_init_type_t));
conf.wifi_mode = STATION;
memcpy(conf.wifi_ssid, init_para_adv->ap_info.ssid, 32);
memcpy(conf.mac_addr, init_para_adv->ap_info.bssid, 6);
conf.channel = init_para_adv->ap_info.channel;
conf.security = init_para_adv->ap_info.security;
memcpy(conf.wifi_key, init_para_adv->key, 64);
// Consider that this API must have PMK, TBD
memcpy(user_pmk, init_para_adv->key, sizeof(user_pmk));
conf.dhcp_mode = init_para_adv->dhcp_mode;
memcpy(conf.local_ip_addr, init_para_adv->local_ip_addr, 16);
memcpy(conf.net_mask, init_para_adv->net_mask, 16);
memcpy(conf.gateway_ip_addr, init_para_adv->gateway_ip_addr, 16);
memcpy(conf.dns_server_ip_addr, init_para_adv->dns_server_ip_addr, 16);
memcpy(conf.reserved, init_para_adv->reserved, 32);
conf.wifi_retry_interval = init_para_adv->wifi_retry_interval;
lega_wlan_register_start_adv_cb(wlan_start_adv_cb);
ret = lega_wlan_open(&conf);
return ret;
}
void wlan_temperature_get_cb(int16_t temperature)
{
// User can update frequence offset according to current temperature
printf("cureent temperature is %d\n", temperature);
}
void register_wlan_temperature_get_cb(uint64_t timer_in_sec, temperature_get_cb_t func)
{
if (func == NULL)
func = wlan_temperature_get_cb;
lega_wlan_register_temperature_get_cb(func);
lega_wlan_set_temperature_get_timer(timer_in_sec);
}
static int get_ip_stat(hal_wifi_module_t *m, hal_wifi_ip_stat_t *out_net_para, hal_wifi_type_t wifi_type)
{
int ret;
lega_wlan_ip_stat_t *in_status;
if (wifi_type == SOFT_AP)
{
printf("%s SOFT_AP not implemeted yet!\r\n", __func__);
return -1;
}
ret = lega_wlan_get_mac_address_inchar(out_net_para->mac);
if (ret != 0)
{
printf("%s get mac addr failed!\r\n", __func__);
return -1;
}
in_status = lega_wlan_get_ip_status();
if (NULL == in_status)
{
printf("%s get ip status failed!\r\n", __func__);
return -1;
}
out_net_para->dhcp = in_status->dhcp;
memcpy(out_net_para->ip, in_status->ip, sizeof(out_net_para->ip));
memcpy(out_net_para->gate, in_status->gate, sizeof(out_net_para->gate));
memcpy(out_net_para->mask, in_status->mask, sizeof(out_net_para->mask));
memcpy(out_net_para->dns, in_status->dns, sizeof(out_net_para->dns));
memcpy(out_net_para->broadcastip, in_status->ip, sizeof(out_net_para->broadcastip));
return ret;
}
static int get_link_stat(hal_wifi_module_t *m, hal_wifi_link_stat_t *out_stat)
{
int ret;
lega_wlan_link_stat_t status;
ret = lega_wlan_get_link_status(&status);
if (0 == ret)
{
out_stat->is_connected = status.is_connected;
out_stat->wifi_strength = status.wifi_strength;
out_stat->channel = status.channel;
memcpy(out_stat->ssid, status.ssid, 32);
memcpy(out_stat->bssid, status.bssid, 6);
}
return ret;
}
static void start_scan(hal_wifi_module_t *m)
{
lega_wlan_start_scan();
}
static void start_scan_adv(hal_wifi_module_t *m)
{
lega_wlan_start_scan_adv();
}
static int power_off(hal_wifi_module_t *m)
{
printf("WiFi HAL %s not implemeted yet!\r\n", __func__);
return 0;
}
static int power_on(hal_wifi_module_t *m)
{
printf("WiFi HAL %s not implemeted yet!\r\n", __func__);
return 0;
}
static int suspend(hal_wifi_module_t *m)
{
return lega_wlan_suspend();
}
static int suspend_station(hal_wifi_module_t *m)
{
return lega_wlan_suspend_sta();
}
static int suspend_soft_ap(hal_wifi_module_t *m)
{
return lega_wlan_suspend_ap();
}
static int set_channel(hal_wifi_module_t *m, int ch)
{
return lega_wlan_monitor_set_channel(ch);
}
static int get_channel(hal_wifi_module_t *m)
{
return lega_wlan_get_channel();
}
static int get_channel_list(hal_wifi_module_t *m, const uint8_t **chnlist)
{
printf("WiFi HAL %s not implemeted yet!\r\n", __func__);
return 0;
}
static void wlan_monitor_cb(uint8_t*data, int len, int rssi)
{
hal_wifi_link_info_t info;
info.rssi = rssi;
if (aos_monitor_cb) {
aos_monitor_cb(data, len, &info);
}
}
static void wlan_mgmt_monitor_cb(uint8_t*data, int len, int rssi)
{
hal_wifi_link_info_t info;
info.rssi = rssi;
if (aos_mgmt_monitor_cb) {
aos_mgmt_monitor_cb(data, len, &info);
}
}
static void start_monitor(hal_wifi_module_t *m)
{
lega_wlan_start_monitor();
lega_wlan_register_monitor_cb(wlan_monitor_cb);
}
static void stop_monitor(hal_wifi_module_t *m)
{
lega_wlan_stop_monitor();
lega_wlan_register_monitor_cb(NULL);
}
static void register_monitor_cb(hal_wifi_module_t *m, monitor_data_cb_t fn)
{
aos_monitor_cb = fn;
}
static void register_wlan_mgnt_monitor_cb(hal_wifi_module_t *m, monitor_data_cb_t fn)
{
aos_mgmt_monitor_cb = fn;
lega_wlan_register_mgmt_monitor_cb(wlan_mgmt_monitor_cb);
}
static int wlan_send_80211_raw_frame(hal_wifi_module_t *m, uint8_t *buf, int len)
{
return lega_wlan_send_raw_frame(buf, len);
}
void scan_done(lega_wlan_scan_result_t *p_scan_results)
{
if (!p_scan_results->is_scan_adv)
{
hal_wifi_scan_result_t out_scan_results;
memset(&out_scan_results, 0, sizeof(hal_wifi_scan_result_t));
if (p_scan_results->ap_num != 0)
{
out_scan_results.ap_num = p_scan_results->ap_num;
out_scan_results.ap_list = lega_rtos_malloc(sizeof(ap_list_t)*out_scan_results.ap_num);
for (int i=0; i<out_scan_results.ap_num; i++)
{
out_scan_results.ap_list[i].ap_power = p_scan_results->ap_list[i].ap_power;
memcpy(out_scan_results.ap_list[i].ssid, p_scan_results->ap_list[i].ssid, 32);
}
}
sim_aos_wifi_lega.ev_cb->scan_compeleted(&sim_aos_wifi_lega,
&out_scan_results, NULL);
if (out_scan_results.ap_list != NULL)
lega_rtos_free(out_scan_results.ap_list);
}
else
{
hal_wifi_scan_result_adv_t out_scan_results;
memset(&out_scan_results, 0, sizeof(hal_wifi_scan_result_adv_t));
if (p_scan_results->ap_num != 0)
{
out_scan_results.ap_num = p_scan_results->ap_num;
out_scan_results.ap_list = lega_rtos_malloc(sizeof(ap_list_adv_t)*out_scan_results.ap_num);
for (int i=0; i<out_scan_results.ap_num; i++)
{
out_scan_results.ap_list[i].ap_power = p_scan_results->ap_list[i].ap_power;
out_scan_results.ap_list[i].channel = p_scan_results->ap_list[i].channel;
out_scan_results.ap_list[i].security = p_scan_results->ap_list[i].security;
memcpy(out_scan_results.ap_list[i].ssid, p_scan_results->ap_list[i].ssid, 32);
memcpy(out_scan_results.ap_list[i].bssid, p_scan_results->ap_list[i].bssid, 6);
}
}
sim_aos_wifi_lega.ev_cb->scan_adv_compeleted(&sim_aos_wifi_lega,
&out_scan_results, NULL);
if (out_scan_results.ap_list != NULL)
lega_rtos_free(out_scan_results.ap_list);
}
}
void wifi_event_cb(lega_wlan_event_e evt, void* info)
{
if (sim_aos_wifi_lega.ev_cb == NULL)
return;
switch (evt)
{
case WLAN_EVENT_SCAN_COMPLETED:
if (sim_aos_wifi_lega.ev_cb->scan_compeleted == NULL)
return;
lega_wlan_scan_result_t *p_in_scan_results = (lega_wlan_scan_result_t*)info;
scan_done(p_in_scan_results);
break;
case WLAN_EVENT_ASSOCIATED:
if (sim_aos_wifi_lega.ev_cb->para_chg == NULL)
return;
hal_wifi_ap_info_adv_t out_ap_info;
lega_wlan_ap_info_adv_t *p_in_ap_info;
memset(&out_ap_info, 0, sizeof(hal_wifi_ap_info_adv_t));
p_in_ap_info = lega_wlan_get_associated_apinfo();
if (NULL != p_in_ap_info)
{
memcpy(out_ap_info.ssid, p_in_ap_info->ssid, p_in_ap_info->ssid_len);
memcpy(out_ap_info.bssid, p_in_ap_info->bssid, 6);
out_ap_info.channel = p_in_ap_info->channel;
out_ap_info.security = p_in_ap_info->security;
sim_aos_wifi_lega.ev_cb->para_chg(&sim_aos_wifi_lega, &out_ap_info, p_in_ap_info->pwd, p_in_ap_info->pwd_len, NULL);
}
break;
case WLAN_EVENT_CONNECTED:
if (sim_aos_wifi_lega.ev_cb->stat_chg == NULL)
return;
sim_aos_wifi_lega.ev_cb->stat_chg(&sim_aos_wifi_lega, NOTIFY_STATION_UP, NULL);
break;
case WLAN_EVENT_IP_GOT:
if (sim_aos_wifi_lega.ev_cb->ip_got == NULL)
return;
hal_wifi_ip_stat_t ip_stat;
lega_wlan_ip_stat_t *p_in_ip_stat = (lega_wlan_ip_stat_t *)info;
ip_stat.dhcp = p_in_ip_stat->dhcp;
memcpy(ip_stat.ip, p_in_ip_stat->ip, 16);
memcpy(ip_stat.gate, p_in_ip_stat->gate, 16);
memcpy(ip_stat.mask, p_in_ip_stat->mask, 16);
memcpy(ip_stat.dns, p_in_ip_stat->dns, 16);
memcpy(ip_stat.broadcastip, p_in_ip_stat->broadcastip, 16);
lega_wlan_get_mac_address_inchar(ip_stat.mac);
sim_aos_wifi_lega.ev_cb->ip_got(&sim_aos_wifi_lega, &ip_stat, NULL);
#if (WIFI_CONFIG_SUPPORT_LOWPOWER > 0)
/* if config WIFI_CONFIG_SUPPORT_LOWPOWER enable wifi power save
* default */
lega_wlan_set_ps_mode(1);
#endif
break;
case WLAN_EVENT_DISCONNECTED:
if (sim_aos_wifi_lega.ev_cb->stat_chg == NULL)
return;
sim_aos_wifi_lega.ev_cb->stat_chg(&sim_aos_wifi_lega, NOTIFY_STATION_DOWN, NULL);
break;
case WLAN_EVENT_AP_UP:
if (sim_aos_wifi_lega.ev_cb->stat_chg == NULL)
return;
sim_aos_wifi_lega.ev_cb->stat_chg(&sim_aos_wifi_lega, NOTIFY_AP_UP, NULL);
break;
case WLAN_EVENT_AP_DOWN:
if (sim_aos_wifi_lega.ev_cb->stat_chg == NULL)
return;
sim_aos_wifi_lega.ev_cb->stat_chg(&sim_aos_wifi_lega, NOTIFY_AP_DOWN, NULL);
break;
default:
printf("WiFi HAL %s EVENT[%d] not implemeted yet!\r\n", __func__, evt);
break;
}
}
void start_debug_mode(hal_wifi_module_t *m)
{
lega_wlan_start_debug_mode();
}
void stop_debug_mode(hal_wifi_module_t *m)
{
lega_wlan_stop_debug_mode();
}
#if (WIFI_CONFIG_SUPPORT_LOWPOWER > 0)
static int set_listeninterval(hal_wifi_module_t *m, uint8_t listen_interval)
{
int status = -1;
if ((listen_interval != 1) && (listen_interval != 3) && (listen_interval != 10)) {
printf("err: listen interval can only to be set:1 3 10\n");
return -1;
}
status = lega_wlan_set_ps_options(WIFI_CONFIG_RECEIVE_DTIM, listen_interval);
if (status != 0) {
return -1;
}
return 0;
}
static int enter_powersave(hal_wifi_module_t *m, uint8_t recvDTIMs)
{
int status = -1;
printf("enter_powersave\n");
status = lega_wlan_set_ps_mode(1);
if (status != 0) {
return -1;
}
return 0;
}
static int exit_powersave(hal_wifi_module_t *m)
{
int status = -1;
printf("exit_powersave\n");
status = lega_wlan_set_ps_mode(0);
if (status == 0) {
return 0;
} else {
return -1;
}
}
#endif
hal_wifi_module_t sim_aos_wifi_lega = {
.base.name = "sim_aos_wifi_lega",
.init = wifi_init,
.get_mac_addr = wifi_get_mac_addr,
.set_mac_addr = wifi_set_mac_addr,
.start = wifi_start,
.start_adv = wifi_start_adv,
.get_ip_stat = get_ip_stat,
.get_link_stat = get_link_stat,
.start_scan = start_scan,
.start_scan_adv = start_scan_adv,
.power_off = power_off,
.power_on = power_on,
.suspend = suspend,
.suspend_station = suspend_station,
.suspend_soft_ap = suspend_soft_ap,
.set_channel = set_channel,
.get_channel = get_channel,
.get_channel_list = get_channel_list,
.start_monitor = start_monitor,
.stop_monitor = stop_monitor,
.register_monitor_cb = register_monitor_cb,
.register_wlan_mgnt_monitor_cb = register_wlan_mgnt_monitor_cb,
.wlan_send_80211_raw_frame = wlan_send_80211_raw_frame,
.start_ap = wifi_start_ap,
.stop_ap = wifi_stop_ap,
.start_debug_mode = start_debug_mode,
.stop_debug_mode = stop_debug_mode,
#if (WIFI_CONFIG_SUPPORT_LOWPOWER > 0)
.set_listeninterval = set_listeninterval,
.enter_powersave = enter_powersave,
.exit_powersave = exit_powersave,
#endif
};

View file

@ -0,0 +1,7 @@
OTA_BIN_OUTPUT_FILE := $(LINK_OUTPUT_FILE:$(LINK_OUTPUT_SUFFIX)=.ota$(BIN_OUTPUT_SUFFIX))
EXTRA_POST_BUILD_TARGETS += $(OTA_BIN_OUTPUT_FILE)
$(OTA_BIN_OUTPUT_FILE):
$(PYTHON) platform/mcu/asr5501/ota.py $(BIN_OUTPUT_FILE)
$(PYTHON) platform/mcu/asr5501/add_md5.py $(OTA_BIN_OUTPUT_FILE)

View file

@ -0,0 +1,18 @@
import os
import sys
import struct
import shutil
workdir = os.path.dirname(os.path.abspath(sys.argv[0]))
if sys.platform == 'linux2':
xzpath = 'xz'
else:
xzpath = os.path.join(workdir, 'xz', 'osx/xz' if sys.platform == 'darwin' else 'win/xz.exe').replace('\\', '/')
rawfile = sys.argv[1]
rawsize = os.path.getsize(rawfile)
xzfile = rawfile.replace('.bin', '.bin.xz')
otafile = rawfile.replace('.bin', '.ota.bin')
os.system('%s --lzma2=dict=32KiB --check=crc32 -k %s' % (xzpath, rawfile))
open(xzfile, 'ab').write(struct.pack('<L', rawsize))
shutil.move(xzfile, otafile)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <aos_main.h>
#include <k_api.h>
#include <aos/kernel.h>
#include <aos/init.h>
#define AOS_START_STACK 2048
ktask_t *g_aos_init;
extern void board_init(void);
static kinit_t kinit = {
.argc = 0,
.argv = NULL,
.cli_enable = 1
};
static void sys_init(void)
{
int i = 0;
soc_system_init();
#ifdef BOOTLOADER
main();
#else
board_init();
aos_kernel_init(&kinit);
#endif
}
void sys_start(void)
{
aos_init();
soc_driver_init();
krhino_task_dyn_create(&g_aos_init, "aos-init", 0, AOS_DEFAULT_APP_PRI, 0, AOS_START_STACK, sys_init, 1);
aos_start();
}

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef AOS_MAIN_H
#define AOS_MAIN_H
void soc_driver_init(void);
void soc_system_init(void);
void sys_start(void);
#endif /* AOS_MAIN_H */

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <aos/aos.h>
#include "hal/soc/soc.h"
#ifdef AOS_BINS
const int *syscall_ktbl = NULL;
const int *syscall_ftbl = NULL;
extern unsigned int _app_data_ram_begin;
extern unsigned int _app_data_ram_end;
extern unsigned int _app_data_flash_begin;
extern unsigned int _app_bss_start;
extern unsigned int _app_bss_end;
extern unsigned int _app_heap_start;
extern unsigned int _app_heap_end;
extern int application_start(int argc, char **argv);
int aos_application_init(void)
{
LOG("aos application init.");
return 0;
}
static void app_entry(void *ksyscall_tbl, void *fsyscall_tbl, int argc, char *argv[])
{
/* syscall_ktbl & syscall_ftbl assignment must be first */
syscall_ktbl = (int *)ksyscall_tbl;
syscall_ftbl = (int *)fsyscall_tbl;
aos_application_init();
application_start(argc, argv);
}
__attribute__ ((used, section(".app_info"))) struct app_info_t app_info = {
app_entry,
&_app_data_ram_begin,
&_app_data_ram_end,
&_app_data_flash_begin,
&_app_bss_start,
&_app_bss_end,
&_app_heap_start,
&_app_heap_end
};
#endif

View file

@ -0,0 +1,9 @@
NAME := app_runtime
$(NAME)_TYPE := app
#GLOBAL_INCLUDES += include
# don't modify to L_CFLAGS, because CONFIG_CJSON_WITHOUT_DOUBLE should enable global
GLOBAL_LDFLAGS += -uapp_info
$(NAME)_SOURCES := app_runtime.c

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <aos/aos.h>
#include "hal/soc/soc.h"
#ifdef AOS_BINS
const int *syscall_ktbl = NULL;
extern void *syscall_ftbl[];
extern char app_info_addr;
struct app_info_t *app_info = (struct app_info_t *)&app_info_addr;
extern unsigned int _framework_data_ram_begin;
extern unsigned int _framework_data_ram_end;
extern unsigned int _framework_data_flash_begin;
extern unsigned int _framework_bss_start;
extern unsigned int _framework_bss_end;
extern unsigned int _framework_heap_start;
extern unsigned int _framework_heap_end;
static void framework_entry(void *syscall_tbl, int argc, char *argv[])
{
/* syscall_ktbl assignment must be first */
syscall_ktbl = (int *)syscall_tbl;
#ifdef AOS_FRAMEWORK_COMMON
aos_framework_init();
#endif
/*app_pre_init();*/
if (app_info->app_entry) {
app_info->app_entry(syscall_tbl, (void *)syscall_ftbl, 0, NULL);
}
}
__attribute__ ((used, section(".framework_info"))) struct framework_info_t framework_info = {
framework_entry,
&_framework_data_ram_begin,
&_framework_data_ram_end,
&_framework_data_flash_begin,
&_framework_bss_start,
&_framework_bss_end,
&_framework_heap_start,
&_framework_heap_end
};
#endif

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