build: W600-SDK importiert, Firmware-Build und Hello am EVK

Docker-Build mit gcc-arm-none-eabi 4.9-2014q4 (statt Homebrew-Cask) verwendet,
Dockerfile/tools/docker.sh dafür aus Task 13 vorgezogen. cmake/sdk.cmake schont
gcc 4.9 (kennt -fcommon/-Wno-error=... nicht). Zwei zusätzliche SDK-Stubs
(EarlyInit, pre_gpio_config) in src/sys/sdk_stubs.c ergänzt, siehe sdk/PATCHES.md.
This commit is contained in:
Michael Sauer
2026-09-11 12:52:26 +02:00
parent 4e7ff78fc6
commit 1b0501179d
610 changed files with 224089 additions and 0 deletions
+291
View File
@@ -0,0 +1,291 @@
/**************************************************************************//**
* @file wm_i2s.c
* @author
* @version
* @date
* @brief
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved.
*****************************************************************************/
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "wm_regs.h"
#include "wm_7816.h"
#include "wm_gpio.h"
#include "wm_uart.h"
#include "wm_cpu.h"
#include "wm_osal.h"
#define DEBUG_7816 1
#if DEBUG_7816
#define PRINT_DEBUG(fmt, args...) do{(printf("[DEBUG] "), printf(fmt, ##args));}while(0)
#else
#define PRINT_DEBUG(fmt, args...)
#endif
#define SYS_CLK (40000000)
sc_io_map sc_io;
/**
* @brief
* This function is used to config the pin in gpio or 7816 mode for the 7816 power on timing
* @param[in] mode : 1--gpio mode ; 0--7816 mode
* @retval
*/
void wm_sc_io_clk_config(uint8_t mode)
{
if (sc_io.initialed == 0)
{
printf("error : 7816 io map must init....\r\n");
return ;
}
if (mode) //gpio mode
{
tls_io_cfg_set(sc_io.clk_pin_num, WM_IO_OPTION5);
tls_io_cfg_set(sc_io.io_pin_num, WM_IO_OPTION5);
tls_gpio_cfg(sc_io.clk_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_cfg(sc_io.io_pin_num, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
}
else //7816 mode
{
tls_io_cfg_set(sc_io.clk_pin_num, sc_io.clk_opt);
tls_io_cfg_set(sc_io.io_pin_num, sc_io.io_opt);
}
}
/**
* @brief
* This function is used to config the block guard time param in 7816 mode
* @param[in] bgt : the value of blcok guard time will be set
* @retval
*/
void wm_sc_set_bgt(uint8_t bgt)
{
uint32_t reg;
bgt = (bgt > 0x1f) ? 0x1F : bgt;
reg = tls_reg_read32(HR_UART2_LINE_CTRL);
reg &= ~(0x1f << 11);
reg |= (bgt << 11);
tls_reg_write32(HR_UART2_LINE_CTRL, reg);
}
/**
* @brief
* This function is used to config the tx retry count when detect err signal
* @param[in] count : the value of retry time will be set 7 for max
* @retval
*/
void wm_sc_tx_retry_times(uint8_t count)
{
uint32_t reg;
reg = tls_reg_read32(HR_UART2_LINE_CTRL);
reg &= ~(0x7 << 16);
tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<16));
tls_bitband_write(HR_UART2_LINE_CTRL, 19, 1);
}
/**
* @brief
* This function is used to config the rx retry count when detect parity error
* @param[in] count : the value of retry time will be set 7 for max
* @retval
*/
void wm_sc_rx_retry_times(uint8_t count)
{
uint32_t reg;
reg = tls_reg_read32(HR_UART2_LINE_CTRL);
reg &= ~(0x7 << 20);
tls_reg_write32(HR_UART2_LINE_CTRL, reg|(count<<20));
tls_bitband_write(HR_UART2_LINE_CTRL, 23, 1);
}
/**
* @brief
* This function is used to config the etu param
* @param[in] etu : the value of etu will be set
* @retval
*/
void wm_sc_set_etu(uint16_t etu)
{
uint32_t reg;
reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL);
reg &= ~ 0xFFFF;
reg |= etu;
tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg);
}
/**
* @brief
* This function config the module clock freq
* @param[in] freq : the value of clock freq
* @retval
*/
void wm_sc_set_frequency(uint32_t freq)
{
uint32_t reg;
uint8_t div;
tls_sys_clk clk;
tls_sys_clk_get(&clk);
div = (clk.apbclk * 1000000 + freq)/(2 * freq) - 1;
reg = tls_reg_read32(HR_UART2_BAUD_RATE_CTRL);
reg &= ~ 0x3F0000;
reg |= (div<<16);
tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, reg);
}
/**
* @brief
* close af to use PB29 and PB30(uart2_rx as default if af is on) as gpio
* @retval
*/
void wm_sc_powerInit(void)
{
#ifdef WM_SC_PWR_PIN
u32 regValue;
// PB29 AF close, used as GPIO
regValue = tls_reg_read32(HR_GPIOB_AFSEL);
regValue &= ~0x20000000;
tls_reg_write32(HR_GPIOB_AFSEL, regValue);
// PB30 AF close, used as GPIO
regValue = tls_reg_read32(HR_GPIOB_AFSEL);
regValue &= ~0x40000000;
tls_reg_write32(HR_GPIOB_AFSEL, regValue);
#endif
}
/**
* @brief
* power on the 7816 device if power is controled by GPIO
* @retval
*/
void wm_sc_poweron(void)
{
#ifdef WM_SC_PWR_PIN
tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_write(WM_SC_PWR_PIN, 1);
#endif
}
/**
* @brief
* power off the 7816 device if power is controled by GPIO
* @retval
*/
void wm_sc_poweroff(void)
{
#ifdef WM_SC_PWR_PIN
tls_gpio_cfg(WM_SC_PWR_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_write(WM_SC_PWR_PIN, 0);
#endif
}
/**
* @brief
* driver the reset gpio in low level
* @retval
*/
void wm_sc_rst_low(void)
{
#ifdef WM_SC_RST_PIN
tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_write(WM_SC_RST_PIN, 0);
#endif
}
/**
* @brief
* driver the reset gpio in high level
* @retval
*/
void wm_sc_rst_high(void)
{
#ifdef WM_SC_RST_PIN
tls_gpio_cfg(WM_SC_RST_PIN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_write(WM_SC_RST_PIN, 1);
#endif
}
/**
* @brief
* hotrest the 7816 device obey the 7816-3 timing
* @retval
*/
void wm_sc_hotreset(void)
{
uint32_t delay = 0xffff;
/* set the rst pin to low */
wm_sc_rst_low();
/* delay */
while(delay--);
/* set f/d to default 372 */
wm_sc_set_etu(WM_SC_DEFAULT_FD);
/* set the rst pin to high */
wm_sc_rst_high();
}
/**
* @brief
* colreset the 7816 device obey the 7816-3 timing
* @retval
*/
void wm_sc_colreset(void)
{
/* power down */
wm_sc_poweroff();
/* select the clk io in gpio mode */
wm_sc_io_clk_config(1);
/* reset the clk pin */
tls_gpio_write(sc_io.clk_pin_num, 0);
/* reset the io pin */
tls_gpio_write(sc_io.io_pin_num, 0);
/* set the ret pin to low */
wm_sc_rst_low();
/* power on the card */
wm_sc_poweron();
/* config the model in 7816 mode */
wm_sc_7816_mode(1);
/* select the clk io pin in 7816 mode */
wm_sc_io_clk_config(0);
/* config the output clock freq*/
wm_sc_set_frequency(5000000);
/* set the F/D to default (372)*/
wm_sc_set_etu(WM_SC_DEFAULT_FD);
/* set the rst pin to high */
wm_sc_rst_high();
}
/**
* @brief
* deactive the 7816 device obey the 7816-3 timing
* @retval
*/
void wm_sc_deactive(void)
{
/* set the rst pin in low level*/
wm_sc_rst_low();
/* select the clk and io pin to 7816 mode */
wm_sc_io_clk_config(0);
/* disable the output clock */
wm_sc_clk_enable(0);
/* select the clk and io pin to gpio mode */
wm_sc_io_clk_config(1);
/* set the clk pin to low */
tls_gpio_write(sc_io.clk_pin_num, 0);
/* set the io pin to low */
tls_gpio_write(sc_io.io_pin_num, 0);
/* set the power pin to low */
wm_sc_poweroff();
}
+64
View File
@@ -0,0 +1,64 @@
# THE VERSION NUMBER
SET(CMAKE_SYSTEM_NAME Generic)
CMAKE_MINIMUM_REQUIRED (VERSION 3.10)
PROJECT(WMDRIVER)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "")
set(CMAKE_VERBOSE_MAKEFILE OFF)
# ENABLE ASM
ENABLE_LANGUAGE(ASM)
SET(CMAKE_STATIC_LIBRARY_PREFIX)
SET(CMAKE_STATIC_LIBRARY_SUFFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX)
# C FLAGS
SET(CMAKE_C_FLAGS " -mthumb --function-sections --data-sections -mcpu=cortex-m3 -std=gnu99 -mabi=aapcs -march=armv7-m -fno-builtin ")
STRING(APPEND CMAKE_C_FLAGS " -DGCC_COMPILE=1 -DWOLFSSL_USER_SETTINGS -D_IN_ADDR_T_DECLARED -D__MACHINE_ENDIAN_H__ -D_TIMEVAL_DEFINED -D__INSIDE_CYGWIN_NET__ ")
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g3 -gdwarf-2 -Wall -DDEBUG ")
SET(CMAKE_C_FLAGS_RELEASE "-Os -Wall")
# DEBUG ASM FLAGS
SET(CMAKE_ASM_FLAGS_DEBUG "${CMAKE_ASM_FLAGS_DEBUG} -O0 -g3 -gdwarf-2 -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin -DDEBUG ")
SET(CMAKE_ASM_FLAGS_RELEASE "${CMAKE_ASM_FLAGS_RELEASE} -Os -Wall -mthumb-interwork -mthumb -std=gnu99 -mcpu=cortex-m3 -march=armv7-m -mabi=aapcs -fno-builtin ")
# Library sources
SET(LIBRARY_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/adc/wm_adc.c"
"${CMAKE_CURRENT_SOURCE_DIR}/cpu/wm_cpu.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dma/wm_dma.c"
"${CMAKE_CURRENT_SOURCE_DIR}/efuse/wm_efuse.c"
"${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls.c"
"${CMAKE_CURRENT_SOURCE_DIR}/flash/wm_fls_gd25qxx.c"
"${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio.c"
"${CMAKE_CURRENT_SOURCE_DIR}/gpio/wm_gpio_afsel.c"
"${CMAKE_CURRENT_SOURCE_DIR}/hspi/wm_hspi.c"
"${CMAKE_CURRENT_SOURCE_DIR}/i2c/wm_i2c.c"
"${CMAKE_CURRENT_SOURCE_DIR}/irq/wm_irq.c"
"${CMAKE_CURRENT_SOURCE_DIR}/pwm/wm_pwm.c"
"${CMAKE_CURRENT_SOURCE_DIR}/pmu/wm_pmu.c"
"${CMAKE_CURRENT_SOURCE_DIR}/rtc/wm_rtc.c"
"${CMAKE_CURRENT_SOURCE_DIR}/spi/wm_hostspi.c"
"${CMAKE_CURRENT_SOURCE_DIR}/timer/wm_timer.c"
"${CMAKE_CURRENT_SOURCE_DIR}/uart/wm_uart.c"
"${CMAKE_CURRENT_SOURCE_DIR}/watchdog/wm_watchdog.c"
"${CMAKE_CURRENT_SOURCE_DIR}/internalflash/wm_internal_fls.c"
"${CMAKE_CURRENT_SOURCE_DIR}/i2s/wm_i2s.c"
"${CMAKE_CURRENT_SOURCE_DIR}/io/wm_io.c"
"${CMAKE_CURRENT_SOURCE_DIR}/lcd/wm_lcd.c"
"${CMAKE_CURRENT_SOURCE_DIR}/7816/wm_7816.c"
)
function(ADD_LIB_TARGET LIBTARGET)
add_library(${LIBTARGET} OBJECT ${LIBRARY_SOURCES})
# ADD_CUSTOM_COMMAND(TARGET ${LIBTARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXECUTABLE_OUTPUT_PATH}/${LIBTARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../../Lib/GNU/${LIBTARGET})
endfunction()
ADD_LIB_TARGET(wmdriver.a)
+517
View File
@@ -0,0 +1,517 @@
/*****************************************************************************
*
* File Name : wm_adc.c
*
* Description: adc Driver Module
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
* All rights reserved.
*
* Author : dave
*
* Date : 2014-8-15
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wm_regs.h"
#include "wm_adc.h"
#include "wm_dma.h"
#include "misc.h"
#include "wm_io.h"
#include "wm_irq.h"
static u16 adc_offset = 0;
volatile ST_ADC gst_adc;
volatile u8 adc_irq_flag = 0;
void ADC_IRQHandler(void)
{
u16 adcvalue;
int reg;
reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
if(reg & CONFIG_ADC_INT) //ADC�ж�
{
adc_irq_flag = 1;
tls_adc_clear_irq(ADC_INT_TYPE_ADC);
adcvalue = tls_read_adc_result();
if(gst_adc.adc_cb)
gst_adc.adc_cb(&adcvalue,1);
}
if(reg & CONFIG_ADC_INT_CMP)
{
tls_adc_clear_irq(ADC_INT_TYPE_ADC_COMP);
if(gst_adc.adc_bigger_cb)
gst_adc.adc_bigger_cb(NULL, 0);
}
}
static void adc_dma_isr_callbk(void)
{
if(gst_adc.adc_dma_cb)
gst_adc.adc_dma_cb((u16 *)(ADC_DEST_BUFFER_DMA), gst_adc.valuelen);
}
void tls_adc_init(u8 ifusedma,u8 dmachannel)
{
tls_reg_write32(HR_SD_ADC_CONFIG_REG, 0x0);
tls_irq_enable(ADC_IRQn);
//ע���жϺ�channel�йأ�������Ҫ������
if(ifusedma)
{
gst_adc.dmachannel = tls_dma_request(dmachannel, 0); //����dma����Ҫֱ��ָ������Ϊ�����dma���ܻᱻ�������ʹ��
tls_dma_irq_register(gst_adc.dmachannel, (void(*)(void*))adc_dma_isr_callbk, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
}
//printf("\ndma channel = %d\n",gst_adc.dmachannel);
}
void tls_adc_clear_irq(int inttype)
{
int reg;
reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
if(ADC_INT_TYPE_ADC == inttype)
{
reg |= CONFIG_ADC_INT;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg);
}
else if(ADC_INT_TYPE_ADC_COMP== inttype)
{
reg |= CONFIG_ADC_INT_CMP;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg);
}
else if(ADC_INT_TYPE_DMA == inttype)
{
tls_dma_irq_clr(gst_adc.dmachannel, TLS_DMA_IRQ_TRANSFER_DONE);
}
}
void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len))
{
if(ADC_INT_TYPE_ADC == inttype)
{
gst_adc.adc_cb = callback;
}
else if(ADC_INT_TYPE_DMA == inttype)
{
gst_adc.adc_dma_cb = callback;
}
else if(ADC_INT_TYPE_ADC_COMP == inttype)
{
gst_adc.adc_bigger_cb = callback;
}
}
u16 tls_read_adc_result(void)
{
u32 value;
u16 ret;
value = tls_reg_read32(HR_SD_ADC_RESULT_REG);
ret = value&0x3fff;
return ret;
}
void tls_adc_start_with_cpu(int Channel)
{
u32 value;
Channel &= CONFIG_ADC_CHL_MASK;
/* Stop adc first */
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_DMA_MASK;
value &= ~CONFIG_ADC_START;
value |= Channel;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_START;
value |= CONFIG_ADC_INT_MASK;
if(Channel < 8)
{
value |= CONFIG_ADC_G_CTRL12;
value &= ~ CONFIG_ADC_VCM(0x3F);
value |= CONFIG_ADC_VCM(0x1F);
}
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
}
void tls_adc_enable_calibration_buffer_offset(void)
{
u32 value;
/* Stop adc first */
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_DMA_MASK;
value &= ~CONFIG_ADC_START;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_CHL_OFFSET;
value |= CONFIG_ADC_START;
value |= CONFIG_ADC_INT_MASK;
value |= CONFIG_ADC_EN_CAL;
value |= CONFIG_ADC_G_CTRL12;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
}
void tls_adc_temp_offset_with_cpu(u8 calTemp12)
{
u32 value;
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_DMA_MASK;
value &= ~CONFIG_ADC_START;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_CHL_TEMP;
value |= CONFIG_ADC_START;
value |= CONFIG_ADC_INT_MASK;
if(calTemp12)
{
value |= CONFIG_ADC_CAL_OFFSET_TEMP12;
}
else
{
value &= ~CONFIG_ADC_CAL_OFFSET_TEMP12;
}
value &= ~CONFIG_ADC_G_CTRL12;
value |= CONFIG_ADC_TEMP_ON;
value |= CONFIG_ADC_G_TEMP12(3);
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/
}
void tls_adc_voltage_start_with_cpu(void)
{
u32 value;
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_DMA_MASK;
value &= ~CONFIG_ADC_START;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_CHL_VOLT;
value |= CONFIG_ADC_START;
value |= CONFIG_ADC_INT_MASK;
value |= CONFIG_ADC_G_CTRL12;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/
}
void tls_adc_start_with_dma(int Channel, int Length)
{
u32 value;
int len;
if(Channel < 0 || Channel > 11)
return;
if(Length > ADC_DEST_BUFFER_SIZE)
len = ADC_DEST_BUFFER_SIZE;
else
len = Length;
gst_adc.valuelen = len;
Channel &= CONFIG_ADC_CHL_MASK;
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_START; //stop
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
/* Stop dma if necessary */
while(DMA_CHNLCTRL_REG(gst_adc.dmachannel) & 1)
{
DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 2;
}
DMA_SRCADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG;
DMA_DESTADDR_REG(gst_adc.dmachannel) = ADC_DEST_BUFFER_DMA;
/* Hard, Normal, adc_req */
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
if (Channel == 8){
DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (0+6)<<2);
value |= (0x1 << 11);
}
else if (Channel == 9){
DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (2+6)<<2);
value |= (0x1 << 13);
}
else if (Channel == 10){
DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (4+6)<<2);
value |= (0x1 << 15);
}
else if (Channel == 11){
DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (6+6)<<2);
value |= (0x1 << 17);
}
else{
DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (Channel+6)<<2);
value |= (0x1 << (11 + Channel));
}
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
/* Dest_add_inc, halfword, */
DMA_CTRL_REG(gst_adc.dmachannel) = (1<<3)|(1<<5)|((len*2)<<8);
DMA_INTMASK_REG &= ~(0x01 << (gst_adc.dmachannel *2 + 1));
DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 1; /* Enable dma */
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_START;
value |= Channel;
if(Channel < 8)
{
value |= CONFIG_ADC_G_CTRL12;
value &= ~ CONFIG_ADC_VCM(0x3F);
value |= CONFIG_ADC_VCM(0x1F);
}
// printf("config value==%x\n", value);
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/
}
void tls_adc_stop(int ifusedma)
{
u32 value;
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_START;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
if(ifusedma)
tls_dma_free(gst_adc.dmachannel);
}
void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol)
{
u32 value;
cmp_data &= 0x3FFF;
value = tls_reg_read32(HR_SD_ADC_RESULT_REG);
value &= ~(0x3FFF<<14);
value |= (cmp_data<<14);
tls_reg_write32(HR_SD_ADC_RESULT_REG, value);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_CMP_INT_MASK;
if(cmp_pol)
{
value |= CONFIG_ADC_CMP_POL;
}
else
{
value &= ~CONFIG_ADC_CMP_POL;
}
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
}
void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol)
{
u32 value;
Channel &= CONFIG_ADC_CHL_MASK;
/* Stop adc first */
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value &= ~CONFIG_ADC_DMA_MASK;
value &= ~CONFIG_ADC_START;
value |= Channel;
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
tls_adc_config_cmp_reg(cmp_data, cmp_pol);
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
value |= CONFIG_ADC_START;
if(Channel < 8)
{
value |= CONFIG_ADC_G_CTRL12;
value &= ~ CONFIG_ADC_VCM(0x3F);
value |= CONFIG_ADC_VCM(0x1F);
}
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/
}
void tls_adc_reference_sel(int ref)
{
u32 value;
value = tls_reg_read32(HR_SD_ADC_CONFIG_REG);
if(ADC_REFERENCE_EXTERNAL == ref)
{
value &= ~CONFIG_ADC_REF_SEL;
value |= CONFIG_ADC_BUF_BYPASS;
}
else if(ADC_REFERENCE_INTERNAL == ref)
{
value |= CONFIG_ADC_REF_SEL;
value &= ~CONFIG_ADC_BUF_BYPASS;
}
tls_reg_write32(HR_SD_ADC_CONFIG_REG, value);
}
void tls_adc_set_clk(int div)
{
u32 value;
value = tls_reg_read32(HR_CLK_DIV_CTL);
value &= ~(0xffff<<12);
value |= (div << 12);
value |= ((u32)0x1<<31);
tls_reg_write32(HR_CLK_DIV_CTL, value);
}
void signedToUnsignedData(u16 *adcValue, u16 *offset)
{
// s16 temp = 0;
if(*adcValue >= 8192)
{
*adcValue -= 8192;
}
else
{
*adcValue += 8192;
}
/* if (*offset >=8192)
{
temp =((*offset-1)&0x1FFF) - 8192;
}else{
temp = *offset;
}
*adcValue -= temp;
*/
}
static void waitForAdcDone(void)
{
while(1)
{
if(adc_irq_flag) //ADC�ж�
{
adc_irq_flag = 0;
break;
}
}
}
static void waitForStable(void)
{
volatile u32 count;
count = 2000;
while( count-- );
}
u16 adc_get_offset(void)
{
tls_adc_init(0, 0);
tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
adc_irq_flag = 0;
waitForStable();
tls_adc_enable_calibration_buffer_offset(); //ʹ��У׼����
waitForAdcDone();
adc_offset = tls_read_adc_result(); //��ȡadcת�����
tls_adc_stop(0);
//printf("\r\noffset:%d", adc_offset);
return adc_offset;
}
u32 adc_get_interTemp(void)
{
u16 code2, code1, realCode;
u32 tem;
tls_adc_init(0, 0);
tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
adc_irq_flag = 0;
waitForStable();
tls_adc_temp_offset_with_cpu(1); //code2
waitForAdcDone();
code2 = tls_read_adc_result();
tls_adc_stop(0);
signedToUnsignedData(&code2, &adc_offset);
adc_irq_flag = 0;
waitForStable();
tls_adc_temp_offset_with_cpu(0); //code1
waitForAdcDone();
code1 = tls_read_adc_result();
tls_adc_stop(0);
signedToUnsignedData(&code1, &adc_offset);
realCode = ( (code1-code2)/2+8192 );
//printf("code1:%d, code2:%d, realCode:%d\r\n", code1, code2, realCode);
//printf("\r\nTEMP:%.1f", realCode*0.12376-1294.58);
//return (realCode*0.12376-1294.58);
tem = realCode*124-1294580;
//printf("tem:%d\r\n", tem);
return tem;
}
u16 adc_get_inputVolt(u8 channel)
{
u16 average = 0;
/*calibration*/
adc_get_offset();
/*get value*/
tls_adc_init(0, 0);
tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
adc_irq_flag = 0;
waitForStable();
tls_adc_start_with_cpu(channel);
waitForAdcDone();
average = tls_read_adc_result();
tls_adc_stop(0);
signedToUnsignedData(&average, &adc_offset);
//printf("ch[%d]inputVolt:%.3f\r\n", channel+1, ((average-8192.0)/8192*2.25/1.2 + 1.584));
return average;
}
u16 adc_get_interVolt(void)
{
u16 voltValue;
/*calibration*/
adc_get_offset();
/*get value*/
tls_adc_init(0, 0);
tls_adc_reference_sel(ADC_REFERENCE_INTERNAL);
adc_irq_flag = 0;
waitForStable();
tls_adc_voltage_start_with_cpu();
waitForAdcDone();
voltValue = tls_read_adc_result();
tls_adc_stop(0);
signedToUnsignedData(&voltValue, &adc_offset);
float voltage = ( 1.214 - ((float)voltValue-8192)/8192*2.25/1.2 )*2;
printf("interVolt:%.2f\r\n", voltage);
return voltValue;
}
u32 adc_temp(void)
{
u32 tem;
adc_get_offset();
tem = adc_get_interTemp();
return tem;
}
+86
View File
@@ -0,0 +1,86 @@
/**
* @file wm_cpu.c
*
* @brief cpu driver module
*
* @author kevin
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include "wm_debug.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_cpu.h"
#include "wm_pwm.h"
#include "wm_uart.h"
#include "wm_wifi.h"
extern void Debug_UartInit(void);
void tls_sys_clock_switch_hook(void)
{
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1);
/*to do, like uart baudrate switch, other device clock switch*/
tls_uart_set_baud_rate(0, 115200);
}
/**
* @brief This function is used to set cpu clock
*
* @param[in] clk select cpu clock
* clk == CPU_CLK_80M 80M
* clk == CPU_CLK_40M 40M
*
* @return None
*
* @note None
*/
void tls_sys_clk_set(u32 clk)
{
u32 RegValue;
u8 wlanDiv, cpuDiv;
RegValue = tls_reg_read32(HR_CLK_DIV_CTL);
wlanDiv = (RegValue>>4)&0x0F;
RegValue &= 0xFFFFF000;
RegValue |= 0x80000000;
switch(clk)
{
case CPU_CLK_40M:
cpuDiv = 4;
break;
default:
cpuDiv = 2;
break;
}
RegValue |= ((wlanDiv*4/cpuDiv)<<8) | (wlanDiv<<4) | cpuDiv;
tls_reg_write32(HR_CLK_DIV_CTL, RegValue);
return;
}
/**
* @brief This function is used to get cpu clock
*
* @param[out] *sysclk point to the addr for system clk output
*
* @return None
*
* @note None
*/
void tls_sys_clk_get(tls_sys_clk *sysclk)
{
u32 value;
value = tls_reg_read32(HR_CLK_DIV_CTL);
sysclk->apbclk = W600_PLL_CLK_MHZ/4/((value>>4)&0x0F);
sysclk->cpuclk = W600_PLL_CLK_MHZ/(value&0x0F);
sysclk->wlanclk = W600_PLL_CLK_MHZ/((value>>4)&0x0F);
}
+405
View File
@@ -0,0 +1,405 @@
/**
* @file wm_dma.c
*
* @brief DMA Driver Module
*
* @author dave
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "misc.h"
#include "wm_dma.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_osal.h"
#include "wm_pmu.h"
static u16 dma_used_bit = 0;
struct tls_dma_channels {
unsigned char channels[8]; /* list of channels */
};
typedef void (*dma_irq_callback)(void *p);
struct dma_irq_context {
u8 flags;
dma_irq_callback burst_done_pf;
void *burst_done_priv;
dma_irq_callback transfer_done_pf;
void *transfer_done_priv;
};
static struct dma_irq_context dma_context[8];
static struct tls_dma_channels channels;
extern void wm_delay_ticks(uint32_t ticks);
static void dma_irq_proc(void *p)
{
unsigned char ch;
unsigned int int_src;
ch = (unsigned char)(unsigned long)p;
int_src = tls_reg_read32(HR_DMA_INT_SRC);
if (ch > 3)
{
for (ch = 4; ch < 8; ch++)
{
if (int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2))
break;
}
if (8 == ch)
return;
}
if ((int_src & (TLS_DMA_IRQ_BOTH_DONE << ch * 2)) &&
(TLS_DMA_IRQ_BOTH_DONE == dma_context[ch].flags))
{
tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
if (dma_context[ch].burst_done_pf)
dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv);
}
else if ((int_src & (TLS_DMA_IRQ_BURST_DONE << ch * 2)) &&
(TLS_DMA_IRQ_BURST_DONE == dma_context[ch].flags))
{
tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
if (dma_context[ch].burst_done_pf)
dma_context[ch].burst_done_pf(dma_context[ch].burst_done_priv);
}
else if ((int_src & (TLS_DMA_IRQ_TRANSFER_DONE << ch * 2)) &&
(TLS_DMA_IRQ_TRANSFER_DONE == dma_context[ch].flags))
{
tls_dma_irq_clr(ch, TLS_DMA_IRQ_BOTH_DONE);
if (dma_context[ch].transfer_done_pf)
dma_context[ch].transfer_done_pf(dma_context[ch].transfer_done_priv);
}
return;
}
void DMA_Channel0_IRQHandler(void)
{
dma_irq_proc((void *)0);
}
void DMA_Channel1_IRQHandler(void)
{
dma_irq_proc((void *)1);
}
void DMA_Channel2_IRQHandler(void)
{
dma_irq_proc((void *)2);
}
void DMA_Channel3_IRQHandler(void)
{
dma_irq_proc((void *)3);
}
void DMA_Channel4_7_IRQHandler(void)
{
dma_irq_proc((void *)4);
}
/**
* @brief This function is used to clear dma interrupt flag.
*
* @param[in] ch Channel no.[0~7]
* @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE.
*
* @return None
*
* @note None
*/
void tls_dma_irq_clr(unsigned char ch, unsigned char flags)
{
unsigned int int_src = 0;
int_src |= flags << 2 * ch;
tls_reg_write32(HR_DMA_INT_SRC, int_src);
return;
}
/**
* @brief This function is used to register dma interrupt callback function.
*
* @param[in] ch Channel no.[0~7]
* @param[in] callback is the dma interrupt call back function.
* @param[in] arg the param of the callback function.
* @param[in] flags Flags setted to TLS_DMA_IRQ_BURST_DONE, TLS_DMA_IRQ_TRANSFER_DONE, TLS_DMA_IRQ_BOTH_DONE.
*
* @return None
*
* @note None
*/void tls_dma_irq_register(unsigned char ch, void (*callback)(void *p), void *arg, unsigned char flags)
{
unsigned int mask;
mask = tls_reg_read32(HR_DMA_INT_MASK);
mask |= TLS_DMA_IRQ_BOTH_DONE << 2 * ch;
mask &= ~(flags << 2 * ch);
tls_reg_write32(HR_DMA_INT_MASK, mask);
dma_context[ch].flags = flags;
if (flags & TLS_DMA_IRQ_BURST_DONE)
{
dma_context[ch].burst_done_pf = callback;
dma_context[ch].burst_done_priv = arg;
}
if (flags & TLS_DMA_IRQ_TRANSFER_DONE)
{
dma_context[ch].transfer_done_pf = callback;
dma_context[ch].transfer_done_priv = arg;
}
if (ch > 3)
ch = 4;
tls_irq_enable(DMA0_INT + ch);
return;
}
/**
* @brief This function is used to Wait until DMA operation completes
*
* @param[in] ch channel no
*
* @retval 0 completed
* @retval -1 failed
*
* @note None
*/
int tls_dma_wait_complt(unsigned char ch)
{
unsigned long timeout = 0;
while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON)
{
tls_os_time_delay(1);
timeout ++;
if(timeout > 500)
return -1;
}
return 0;
}
/**
* @brief This function is used to Start the DMA controller by Wrap
*
* @param[in] ch channel no
* @param[in] dma_desc pointer to DMA channel descriptor structure
* @param[in] auto_reload does restart when current transfer complete
* @param[in] src_zize dource address size
* @param[in] dest_zize destination address size
*
* @retval 1 success
* @retval 0 failed
*
* @note
* DMA Descriptor:
* +--------------------------------------------------------------+
* |Vld[31] | RSV |
* +--------------------------------------------------------------+
* | RSV | Dma_Ctrl[16:0] |
* +--------------------------------------------------------------+
* | Src_Addr[31:0] |
* +--------------------------------------------------------------+
* | Dest_Addr[31:0] |
* +--------------------------------------------------------------+
* | Next_Desc_Add[31:0] |
* +--------------------------------------------------------------+
*/
unsigned char tls_dma_start_by_wrap(unsigned char ch, struct tls_dma_descriptor *dma_desc,
unsigned char auto_reload,
unsigned short src_zize,
unsigned short dest_zize)
{
if((ch > 7) && !dma_desc) return 1;
DMA_SRCWRAPADDR_REG(ch) = dma_desc->src_addr;
DMA_DESTWRAPADDR_REG(ch) = dma_desc->dest_addr;
DMA_WRAPSIZE_REG(ch) = (dest_zize << 16) | src_zize;
DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x1ffff) << 1) | (auto_reload ? 0x1: 0x0);
DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON;
return 0;
}
/**
* @brief This function is used to Start the DMA controller
*
* @param[in] ch channel no
* @param[in] dma_desc pointer to DMA channel descriptor structure
* @param[in] auto_reload does restart when current transfer complete
*
* @retval 0 success
* @retval 1 failed
*
* @note
* DMA Descriptor:
* +--------------------------------------------------------------+
* |Vld[31] | RSV |
* +--------------------------------------------------------------+
* | RSV | Dma_Ctrl[16:0] |
* +--------------------------------------------------------------+
* | Src_Addr[31:0] |
* +--------------------------------------------------------------+
* | Dest_Addr[31:0] |
* +--------------------------------------------------------------+
* | Next_Desc_Add[31:0] |
* +--------------------------------------------------------------+
*/
unsigned char tls_dma_start(unsigned char ch, struct tls_dma_descriptor *dma_desc, unsigned char auto_reload)
{
if((ch > 7) && !dma_desc) return 1;
if ((dma_used_bit &(1<<ch)) == 0)
{
dma_used_bit |= (1<<ch);
}
DMA_SRCADDR_REG(ch) = dma_desc->src_addr;
DMA_DESTADDR_REG(ch) = dma_desc->dest_addr;
DMA_CTRL_REG(ch) = ((dma_desc->dma_ctrl & 0x7fffff) << 1) | (auto_reload ? 0x1: 0x0);
DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_ON;
return 0;
}
/**
* @brief This function is used to To stop current DMA channel transfer
*
* @param[in] ch channel no. to be stopped
*
* @retval 0 success
* @retval 1 failed
*
* @note
* If channel stop, DMA_CHNL_CTRL_CHNL_ON bit in DMA_CHNLCTRL_REG is cleared.
*/
unsigned char tls_dma_stop(unsigned char ch)
{
if(ch > 7) return 1;
if(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON)
{
DMA_CHNLCTRL_REG(ch) |= DMA_CHNL_CTRL_CHNL_OFF;
while(DMA_CHNLCTRL_REG(ch) & DMA_CHNL_CTRL_CHNL_ON);
}
return 0;
}
/**
* @brief This function is used to Request a free dma channel
*
* @param[in] ch channel no.
* @param[in] flags flags setted to selected channel
*
* @return Channel no. that is free now
*
* @note
* If ch is 0, the function will select a random free channel,
* else return the selected channel no.
*/
unsigned char tls_dma_request(unsigned char ch, unsigned char flags)
{
unsigned char freeCh = 0;
int i = 0;
if (ch == 0)
{
for (i = 0; i < 8; i++)
{
if (!(channels.channels[i] & TLS_DMA_FLAGS_CHANNEL_VALID))
{
freeCh = i;
break;
}
}
if (8 == i)
{
printf("!!!there is no free DMA channel.!!!\n");
freeCh = 0;
}
}
else if ((ch >0) && (ch < 8))
{
if (!(channels.channels[ch] & TLS_DMA_FLAGS_CHANNEL_VALID))
{
freeCh = ch;
}
else
{
printf("!!!there is no free DMA channel.!!!\n");
freeCh = 0;
}
}
//if(freeCh != 0)
{
channels.channels[freeCh] = flags | TLS_DMA_FLAGS_CHANNEL_VALID;
DMA_MODE_REG(freeCh) = flags;
}
if (dma_used_bit == 0)
{
tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA);
}
dma_used_bit |= (1<<freeCh);
return freeCh;
}
/**
* @brief This function is used to Free the DMA channel when not use
*
* @param[in] ch channel no. that is ready to free
*
* @return None
*
* @note None
*/
void tls_dma_free(unsigned char ch)
{
if(ch < 8)
{
tls_dma_stop(ch);
DMA_SRCADDR_REG(ch) = 0;
DMA_DESTADDR_REG(ch) = 0;
DMA_MODE_REG(ch) = 0;
DMA_CTRL_REG(ch) = 0;
// DMA_INTSRC_REG = 0xffff;
DMA_INTSRC_REG |= 0x03<<(ch*2);
channels.channels[ch] = 0x00;
dma_used_bit &= ~(1<<ch);
if (dma_used_bit == 0)
{
tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_DMA);
}
}
}
/**
* @brief This function is used to Initialize DMA Control
*
* @param[in] None
*
* @return None
*
* @note None
*/
void tls_dma_init(void)
{
DMA_INTMASK_REG = 0xffff;
DMA_INTSRC_REG = 0xffff;
}
+644
View File
@@ -0,0 +1,644 @@
/**************************************************************************
* File Name : tls_efuse.c
* Author :
* Version :
* Date :
* Description : Use Flash Addr as virtual efuse
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
* All rights reserved.
*
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wm_debug.h"
#include "wm_regs.h"
#include "wm_efuse.h"
#include "wm_config.h"
#include "list.h"
#include "wm_internal_flash.h"
#include "wm_crypto_hard.h"
#include "wm_timer.h"
#include "wm_cpu.h"
#include "wm_irq.h"
#include "wm_flash_map.h"
#include "wm_mem.h"
extern void flashSRRW(unsigned long offset,unsigned char *buf,unsigned long sz, unsigned char *backbuf, unsigned int backlen, unsigned int rd);
#define FT_MAGICNUM_ADDR (FLASH_BASE_ADDR)
#define MAGICNUM_LEN (4)
#define FT_CHECKSUM_ADDR (FT_MAGICNUM_ADDR + MAGICNUM_LEN)
#define CHECKSUM_LEN (4)
#define FT_DATALEN_ADDR (FT_CHECKSUM_ADDR + CHECKSUM_LEN)
#define FT_DATALEN_LEN (4)
#define FT_MAC_ADDR (FT_DATALEN_ADDR + FT_DATALEN_LEN)
#define MAC_ADDR_LEN (8)
#define FT_TX_DC_OFFSET_ADDR (FT_MAC_ADDR + MAC_ADDR_LEN)
#define TX_DC_OFFSET_LEN (4)
#define FT_RX_DC_OFFSET_ADDR (FT_TX_DC_OFFSET_ADDR + TX_DC_OFFSET_LEN)
#define RX_DC_OFFSET_LEN (4)
#define FT_TX_IQ_GAIN_ADDR (FT_RX_DC_OFFSET_ADDR + RX_DC_OFFSET_LEN)
#define TX_IQ_GAIN_LEN (4)
#define FT_RX_IQ_GAIN_ADDR (FT_TX_IQ_GAIN_ADDR + TX_IQ_GAIN_LEN)
#define RX_IQ_GAIN_LEN (4)
#define FT_TX_IQ_PHASE_ADDR (FT_RX_IQ_GAIN_ADDR + RX_IQ_GAIN_LEN)
#define TX_IQ_PHASE_LEN (4)
#define FT_RX_IQ_PHASE_ADDR (FT_TX_IQ_PHASE_ADDR + TX_IQ_PHASE_LEN)
#define RX_IQ_PHASE_LEN (4)
#define FT_GAIN_ADDR (FT_RX_IQ_PHASE_ADDR + RX_IQ_PHASE_LEN)
#define FT_GAIN_LEN (84)
#define FT_FIX_DATA_LEN (MAC_ADDR_LEN + TX_DC_OFFSET_LEN + RX_DC_OFFSET_LEN + TX_IQ_GAIN_LEN + RX_IQ_GAIN_LEN \
+ TX_IQ_PHASE_LEN \
+ RX_IQ_PHASE_LEN)
/* key paramater area -- begin -- */
/** PHY parameter area **/
#define PHY_BASE_ADDR (FLASH_BASE_ADDR)
#define PHY_AREA_LEN (0x1000)
/** QFlash parameter area **/
#define QFLASH_BASE_ADDR (PHY_BASE_ADDR + PHY_AREA_LEN)
#define QFLASH_AREA_LEN (0x1000)
#define QFLASH_HDR_BASE_ADDR (QFLASH_BASE_ADDR)
#define QFLASH_HDR_LEN (12)
#define QFLASH_Sec_Level_BASE_ADDR (QFLASH_HDR_BASE_ADDR + QFLASH_HDR_LEN)
#define QFLASH_Sec_Level_LEN (4)
#define QFLASH_CHIP_ID_BASE_ADDR (QFLASH_Sec_Level_BASE_ADDR + QFLASH_Sec_Level_LEN)
#define QFLASH_CHIP_ID_LEN (16)
/* key parameter area -- end -- */
typedef struct FT_PARAM
{
unsigned int magic_no;
unsigned int checksum;
unsigned int data_len;
unsigned char mac_addr[MAC_ADDR_LEN];
unsigned int tx_dcoffset;
unsigned int rx_dcoffset;
unsigned int tx_iq_gain;
unsigned int rx_iq_gain;
unsigned int tx_iq_phase;
unsigned int rx_iq_phase;
unsigned char tx_gain[FT_GAIN_LEN];
}FT_PARAM_ST;
static u8 default_mac[6] = {0x00,0x25,0x08,0x09,0x01,0x0F};
FT_PARAM_ST gftParam;
int tls_ft_param_init(void)
{
int i = 0;
int usedcnt[2] = {0, 0};
u32 crcvalue = 0;
psCrcContext_t ctx;
u8 *pmem = NULL;
FT_PARAM_ST *pft = NULL;
if (gftParam.magic_no == SIGNATURE_WORD)
{
return TRUE;
}
pmem = tls_mem_alloc(512);
if (pmem == NULL)
{
return FALSE;
}
pft = tls_mem_alloc(sizeof(FT_PARAM_ST));
if (pft == NULL)
{
return FALSE;
}
for (i = 0; i < 2; i++)
{
if (i == 0)
{
tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)pft, sizeof(FT_PARAM_ST));
}else{
flashSRRW(0, (unsigned char *)pft, sizeof(FT_PARAM_ST), pmem, 256, 1);
}
if (pft->magic_no == SIGNATURE_WORD)
{
tls_crypto_init();
tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT);
tls_crypto_crc_update(&ctx, (unsigned char *)pft + 12, sizeof(FT_PARAM_ST) - 12);
tls_crypto_crc_final(&ctx, &crcvalue);
if ((pft->checksum != crcvalue))
{
usedcnt[i] = -1;
continue;
}
if (gftParam.magic_no != SIGNATURE_WORD)
{
memcpy(&gftParam, pft, sizeof(FT_PARAM_ST));
}
}else{
usedcnt[i] = -1;
}
}
if ((usedcnt[0] + usedcnt[1]) == -2)
{
/*Use default ft param*/
}
else if (usedcnt[0] < 0) /*flash param destroyed*/
{
tls_flash_unlock();
tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam));
tls_flash_lock();
}
else if (usedcnt[1] < 0) /*SR param destroyed*/
{
flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0);
}
else
{
if (gftParam.checksum != pft->checksum)
{
flashSRRW(0, (unsigned char *)&gftParam, sizeof(FT_PARAM_ST), pmem, 256, 0);
}
}
tls_mem_free(pmem);
tls_mem_free(pft);
return TRUE;
}
int tls_ft_param_get(unsigned int opnum, void *data, unsigned int rdlen)
{
//FT_PARAM_ST ft;
//tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&ft, sizeof(ft));
switch (opnum)
{
case CMD_MAC: /*MAC*/
if ((gftParam.mac_addr[0]&0x1)
||(0 == (gftParam.mac_addr[0]|gftParam.mac_addr[1]|gftParam.mac_addr[2]|gftParam.mac_addr[3]|gftParam.mac_addr[4]|gftParam.mac_addr[5])))
{
memcpy(data, default_mac, rdlen);
}
else
{
memcpy(data, gftParam.mac_addr, rdlen);
}
break;
case CMD_TX_DC: /*tx_dcoffset*/
*(unsigned int *)data = gftParam.tx_dcoffset;
break;
case CMD_RX_DC: /*rx_dcoffset*/
*(unsigned int *)data = gftParam.rx_dcoffset;
break;
case CMD_TX_IQ_GAIN:
*(unsigned int *)data = gftParam.tx_iq_gain;
break;
case CMD_RX_IQ_GAIN:
*(unsigned int *)data = gftParam.rx_iq_gain;
break;
case CMD_TX_IQ_PHASE:
*(unsigned int *)data = gftParam.tx_iq_phase;
break;
case CMD_RX_IQ_PHASE:
*(unsigned int *)data = gftParam.rx_iq_phase;
break;
case CMD_TX_GAIN: /*gain*/
if (rdlen < FT_GAIN_LEN)
{
memcpy(data, gftParam.tx_gain, rdlen);
}
else
{
memcpy(data, gftParam.tx_gain, FT_GAIN_LEN);
}
break;
default:
return -1;
}
return 0;
}
int tls_ft_param_set(unsigned int opnum, void *data, unsigned int len)
{
psCrcContext_t ctx;
unsigned int writelen = 0;
u8 *pmem = NULL;
if (!data || !len)
{
return -1;
}
//tls_fls_read(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam));
switch (opnum)
{
case CMD_MAC: /*MAC*/
memcpy(gftParam.mac_addr, (unsigned char *)data, len);
break;
case CMD_TX_DC: /*tx_dcoffset*/
gftParam.tx_dcoffset = *(unsigned int *)data;
break;
case CMD_RX_DC: /*rx_dcoffset*/
gftParam.rx_dcoffset = *(unsigned int *)data;
break;
case CMD_TX_IQ_GAIN:
gftParam.tx_iq_gain = *(unsigned int *)data;
break;
case CMD_RX_IQ_GAIN:
gftParam.rx_iq_gain = *(unsigned int *) data;
break;
case CMD_TX_IQ_PHASE:
gftParam.tx_iq_phase = *(unsigned int *)data;
break;
case CMD_RX_IQ_PHASE:
gftParam.rx_iq_phase = *(unsigned int *) data;
break;
case CMD_TX_GAIN: /*gain*/
if (len >= FT_GAIN_LEN)
{
writelen = FT_GAIN_LEN;
}
else
{
writelen = len;
}
memcpy(gftParam.tx_gain, data, writelen);
break;
default:
return -1;
}
tls_crypto_init();
tls_crypto_crc_init(&ctx, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, INPUT_REFLECT | OUTPUT_REFLECT);
gftParam.magic_no = SIGNATURE_WORD;
tls_crypto_crc_update(&ctx, (unsigned char *)&gftParam + 12, sizeof(gftParam) -12);
tls_crypto_crc_final(&ctx, &gftParam.checksum);
tls_flash_unlock();
tls_fls_write(FT_MAGICNUM_ADDR, (unsigned char *)&gftParam, sizeof(gftParam));
tls_flash_lock();
pmem = tls_mem_alloc(512);
if (pmem)
{
flashSRRW(0, (unsigned char *)&gftParam, sizeof(gftParam), pmem, 512, 0);
tls_mem_free(pmem);
}
return 0;
}
/**********************************************************************************************************
* Description: This function is used to get mac addr.
*
* Arguments : mac mac addr,6 byte
*
* Returns : TLS_EFUSE_STATUS_OK get success
* TLS_EFUSE_STATUS_EIO get failed
**********************************************************************************************************/
int tls_get_mac_addr(u8 *mac)
{
return tls_ft_param_get(CMD_MAC, mac, 6);
}
/**********************************************************************************************************
* Description: This function is used to set mac addr.
*
* Arguments : mac mac addr,6 byte
*
* Returns : TLS_EFUSE_STATUS_OK get success
* TLS_EFUSE_STATUS_EIO get failed
**********************************************************************************************************/
int tls_set_mac_addr(u8 *mac)
{
return tls_ft_param_set(CMD_MAC, mac, 6);
}
/**********************************************************************************************************
* Description: This function is used to get tx lod.
*
* Arguments : *txlo
*
* Returns : 0 get success
* -1 get failed
**********************************************************************************************************/
int tls_get_tx_lo(u8 *txlo)
{
return tls_ft_param_get(CMD_TX_DC, txlo, 4);
}
/**********************************************************************************************************
* Description: This function is used to set tx lo.
*
* Arguments : txlo
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_tx_lo(u8 *txlo)
{
return tls_ft_param_set(CMD_TX_DC, txlo, 4);
}
/**********************************************************************************************************
* Description: This function is used to get tx iq gain.
*
* Arguments : txGain
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_get_tx_iq_gain(u8 *txGain)
{
return tls_ft_param_get(CMD_TX_IQ_GAIN, txGain, 4);
}
/**********************************************************************************************************
* Description: This function is used to set tx iq gain.
*
* Arguments : txGain
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_tx_iq_gain(u8 *txGain)
{
return tls_ft_param_set(CMD_TX_IQ_GAIN, txGain, 4);
}
/**********************************************************************************************************
* Description: This function is used to get rx iq gain.
*
* Arguments : rxGain
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_get_rx_iq_gain(u8 *rxGain)
{
return tls_ft_param_get(CMD_RX_IQ_GAIN, rxGain, 4);
}
/**********************************************************************************************************
* Description: This function is used to set rx iq gain.
*
* Arguments : rxGain
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_rx_iq_gain(u8 *rxGain)
{
return tls_ft_param_set(CMD_RX_IQ_GAIN, rxGain, 4);
}
/**********************************************************************************************************
* Description: This function is used to get tx iq phase.
*
* Arguments : txPhase
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_get_tx_iq_phase(u8 *txPhase)
{
return tls_ft_param_get(CMD_TX_IQ_PHASE, txPhase, 4);
}
/**********************************************************************************************************
* Description: This function is used to set tx iq phase.
*
* Arguments : txPhase
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_tx_iq_phase(u8 *txPhase)
{
return tls_ft_param_set(CMD_TX_IQ_PHASE, txPhase, 4);
}
/**********************************************************************************************************
* Description: This function is used to get rx iq phase.
*
* Arguments : rxPhase
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_get_rx_iq_phase(u8 *rxPhase)
{
return tls_ft_param_get(CMD_RX_IQ_PHASE, rxPhase, 4);
}
/**********************************************************************************************************
* Description: This function is used to set tx iq phase.
*
* Arguments : rxPhase
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_rx_iq_phase(u8 *rxPhase)
{
return tls_ft_param_set(CMD_RX_IQ_PHASE, rxPhase, 4);
}
int tls_freq_err_op(u8 *freqerr, u8 flag)
{
tls_flash_unlock();
if (flag){
tls_fls_write(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4);
}
else
{
tls_fls_read(FT_MAGICNUM_ADDR + sizeof(FT_PARAM_ST), freqerr, 4);
}
tls_flash_lock();
return TLS_EFUSE_STATUS_OK;
}
int tls_rf_vcg_ctrl_op(u8 *vcg, u8 flag)
{
tls_flash_unlock();
if (flag){
tls_fls_write(VCG_ADDR, vcg, VCG_LEN);
}
else
{
tls_fls_read(VCG_ADDR, vcg, VCG_LEN);
}
tls_flash_lock();
return TLS_EFUSE_STATUS_OK;
}
/**********************************************************************************************************
* Description: This function is used to get tx gain.
*
* Arguments : txgain tx gain
*
* Returns : 0 get success
* -1 get failed
**********************************************************************************************************/
int tls_get_tx_gain(u8 *txgain)
{
return tls_ft_param_get(CMD_TX_GAIN, txgain, TX_GAIN_LEN);
}
/**********************************************************************************************************
* Description: This function is used to set tx gain.
*
* Arguments : txgain tx gain
*
* Returns : 0 set success
* -1 set failed
**********************************************************************************************************/
int tls_set_tx_gain(u8 *txgain)
{
return tls_ft_param_set(CMD_TX_GAIN, txgain, TX_GAIN_LEN);
}
/**********************************************************************************************************
* Description: This function is used to get uuid
*
* Arguments : *uuid
*
* Returns : 0 get success
* -1 get failed
**********************************************************************************************************/
int tls_get_uuid(u8 *uuid, u8 len)
{
u8 *pmem = NULL;
if (uuid)
{
pmem = tls_mem_alloc(512);
if (pmem == NULL)
{
return TLS_EFUSE_STATUS_ERR;
}
flashSRRW(256, (unsigned char *)pmem, len, pmem, 512, 1);
memcpy(uuid, &pmem[0], len);
tls_mem_free(pmem);
pmem = NULL;
return TLS_EFUSE_STATUS_OK;
}
return TLS_EFUSE_STATUS_ERR;
}
/**********************************************************************************************************
* Description: This function is used to get uuid
*
* Arguments : *uuid :data to be written to otp area
* len : data len to be written
* iflock : if lock the otp area,1-lock, once lock,can not unlock!!!
*
* Returns : 0 get success
* -1 get failed
**********************************************************************************************************/
int tls_set_uuid(u8 *uuid, u8 len, u8 iflock)
{
u8 *pmem = NULL;
if (uuid)
{
pmem = tls_mem_alloc(512);
if (pmem == NULL)
{
return TLS_EFUSE_STATUS_ERR;
}
flashSRRW(256, (unsigned char *)uuid, len, pmem, 512, 0);
if (iflock)
{
writeSRLockBit(2);
}
tls_mem_free(pmem);
pmem = NULL;
return TLS_EFUSE_STATUS_OK;
}
return TLS_EFUSE_STATUS_ERR;
}
#define FF_n16 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff
int tls_get_chipid(u8 chip_id[QFLASH_CHIP_ID_LEN])
{
int ret = 0;
static u8 _chip_id[QFLASH_CHIP_ID_LEN] = { FF_n16 };
u8 zero[QFLASH_CHIP_ID_LEN] = { FF_n16 };
if (!memcmp(_chip_id, zero, QFLASH_CHIP_ID_LEN))
{
ret = tls_fls_read(QFLASH_CHIP_ID_BASE_ADDR, _chip_id, QFLASH_CHIP_ID_LEN);
}
if (0 == ret)
{
memcpy(chip_id, _chip_id, QFLASH_CHIP_ID_LEN);
}
return ret;
}
#undef FF_n16
unsigned int tls_sleep(unsigned int seconds)
{
int ret = 0;
ret = tls_msleep(seconds * 1000);
return ret;
}
int tls_msleep(unsigned int msec)
{
int ret = 0;
ret = tls_delay_via_timer(msec, TIMER_MS_UNIT_FLAG);
return ret;
}
int tls_usleep(unsigned int /*useconds_t*/ usec)
{
int ret = 0;
ret = tls_delay_via_timer(usec, TIMER_US_UNIT_FLAG);
return ret;
}
+577
View File
@@ -0,0 +1,577 @@
/**
* @file wm_fls.c
*
* @brief flash Driver Module
*
* @author dave
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "list.h"
#include "wm_hostspi.h"
#include "wm_flash.h"
#include "wm_dbg.h"
#include "wm_mem.h"
#include "wm_fls_gd25qxx.h"
static struct tls_fls *spi_fls = NULL;
int tls_spifls_read_id(u32 * id)
{
u32 cmd;
int err;
cmd = FLS_CMD_READ_DEV_ID;
*id = 0;
err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, (u8 *) id, 3);
if (err != TLS_SPI_STATUS_OK)
{
TLS_DBGPRT_ERR("flash read ID fail(%d)!\n", err);
return TLS_FLS_STATUS_EIO;
}
TLS_DBGPRT_FLASH_INFO("flash ID - 0x%x.\n", *id);
return TLS_FLS_STATUS_OK;
}
/**
* @brief This function is used to read data from the flash.
*
* @param[in] addr is byte offset addr for read from the flash.
* @param[in] buf is user for data buffer of flash read
* @param[in] len is byte length for read.
*
* @retval TLS_FLS_STATUS_OK if read sucsess
* @retval TLS_FLS_STATUS_EIO if read fail
* @retval TLS_FLS_STATUS_EPERM if flash driver module not beed installed
* @retval TLS_FLS_STATUS_ENODRV if the current spi flash driver not installed
* @retval TLS_FLS_STATUS_EINVAL if parameter error
*
* @note None
*/
int tls_spifls_read(u32 addr, u8 * buf, u32 len)
{
int err;
u32 read_bytes;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|| (buf == NULL))
{
return TLS_FLS_STATUS_EINVAL;
}
tls_os_sem_acquire(spi_fls->fls_lock, 0);
drv = spi_fls->current_drv;
read_bytes =
((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
err = TLS_FLS_STATUS_OK;
err = drv->read(addr, buf, read_bytes);
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
int tls_spifls_fast_read(u32 addr, u8 * buf, u32 len)
{
int err;
u32 read_bytes;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|| (buf == NULL))
{
return TLS_FLS_STATUS_EINVAL;
}
if ((spi_fls->current_drv->flags & TLS_FLS_FLAG_FAST_READ) !=
TLS_FLS_FLAG_FAST_READ)
{
return TLS_FLS_STATUS_ENOSUPPORT;
}
drv = spi_fls->current_drv;
read_bytes =
((addr + len) > drv->total_size) ? (drv->total_size - addr) : len;
err = TLS_FLS_STATUS_OK;
err = drv->fast_read(addr, buf, read_bytes);
return err;
}
int tls_spifls_page_write(u32 page, u8 * buf, u32 page_cnt)
{
int err;
u32 write_pages;
u32 i;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if ((page >= (spi_fls->current_drv->total_size / spi_fls->current_drv->page_size))
|| (page_cnt == 0) || (buf == NULL))
{
return TLS_FLS_STATUS_EINVAL;
}
drv = spi_fls->current_drv;
write_pages = ((page + page_cnt) > (drv->total_size / drv->page_size)) ?
((drv->total_size / drv->page_size) -page) : page_cnt;
err = TLS_FLS_STATUS_OK;
for (i = 0; i < write_pages; i++)
{
err = drv->page_write(page + i, buf + i * drv->page_size);
if (err != TLS_FLS_STATUS_OK)
{
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", (page + i));
break;
}
}
return err;
}
/**
* @brief This function is used to write data to the flash.
*
* @param[in] addr is byte offset addr for write to the flash
* @param[in] buf is the data buffer want to write to flash
* @param[in] len is the byte length want to write
*
* @retval TLS_FLS_STATUS_OK if write flash success
* @retval TLS_FLS_STATUS_EPERM if flash struct point is null
* @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
* @retval TLS_FLS_STATUS_EINVAL if argument is invalid
* @retval TLS_FLS_STATUS_EIO if io error
* @retval TLS_FLS_STATUS_ENOMEM if memory allocation fail
*
* @note None
*/
int tls_spifls_write(u32 addr, u8 * buf, u32 len)
{
u8 *cache;
int err;
u32 sector_addr;
u32 sector_off;
u32 sector_remain;
u32 cntforFF;
u32 write_bytes;
u32 write_page = 0;
u32 i;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if ((addr >= spi_fls->current_drv->total_size) || (len == 0)
|| (buf == NULL))
{
return TLS_FLS_STATUS_EINVAL;
}
tls_os_sem_acquire(spi_fls->fls_lock, 0);
drv = spi_fls->current_drv;
err = TLS_FLS_STATUS_OK;
cache = tls_mem_alloc(drv->sector_size);
if (cache == NULL)
{
tls_os_sem_release(spi_fls->fls_lock);
TLS_DBGPRT_ERR("allocate sector cache memory(%dB) fail!\n",
drv->sector_size);
return TLS_FLS_STATUS_ENOMEM;
}
sector_addr = addr / drv->sector_size; //Section addr
sector_off = (addr % drv->sector_size); //Offset in section
sector_remain = drv->sector_size - sector_off;
write_bytes = len;
TLS_DBGPRT_FLASH_INFO("write to flash: sector address - %d, sector off - %x.\n", sector_addr,
sector_off);
if(write_bytes <= sector_remain)
{
sector_remain = write_bytes; //Not bigger with remain size in section
}
while (1)
{
TLS_DBGPRT_FLASH_INFO("firstly, read the sector - %d to cache.\n", sector_addr);
err = drv->read(sector_addr * drv->sector_size, cache, drv->sector_size);
if (err != TLS_FLS_STATUS_OK)
{
TLS_DBGPRT_ERR("flash read fail(sector %d)!\n", sector_addr);
break;
}
cntforFF = 0;
for(i = 0; i < sector_remain; i++)
{
if(cache[i + sector_off] == 0xFF)
{
cntforFF++;
}
cache[i + sector_off] = buf[i];
}
//If the flash address to be written is all 0xFF, then erase sector is not necessary;
if( cntforFF != sector_remain)
{
TLS_DBGPRT_FLASH_INFO("second, erase the sector - %d.\n", sector_addr);
err = drv->erase(sector_addr);
if (err != TLS_FLS_STATUS_OK)
{
TLS_DBGPRT_ERR("flash erase fail(sector %d)!\n", sector_addr);
break;
}
}
if( (cntforFF != sector_remain ) || ((sector_off == 0) && (sector_remain == drv->sector_size)))
{
for(i = 0; i < (drv->sector_size / drv->page_size); i++)
{
err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]);
if (err != TLS_FLS_STATUS_OK)
{
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i);
tls_mem_free(cache);
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
}
}
else
{
write_page = (sector_off / drv->page_size) == 15 ? 16 : (sector_off + sector_remain) / drv->page_size + 1;
//As long as this sector is not erased in this round, we only program the changed pages instead of all of them.
for(i = (sector_off / drv->page_size); i < write_page; i++)
{
err = drv->page_write(sector_addr * drv->sector_size / drv->page_size + i, &cache[i * drv->page_size]);
if (err != TLS_FLS_STATUS_OK)
{
TLS_DBGPRT_ERR("flash page write fail(page %d)!\n", i);
tls_mem_free(cache);
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
}
}
if(write_bytes == sector_remain)
{
break;
}
else
{
sector_addr++;
sector_off = 0;
buf += sector_remain;
write_bytes -= sector_remain;
if(write_bytes > (drv->sector_size))
sector_remain = drv->sector_size;
else
sector_remain = write_bytes; //Next section will finish
}
}
tls_mem_free(cache);
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
int tls_spifls_erase(u32 sector)
{
int err;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if (sector >= (spi_fls->current_drv->total_size / spi_fls->current_drv->sector_size))
{
TLS_DBGPRT_ERR("the sector to be erase overflow!\n");
return TLS_FLS_STATUS_EINVAL;
}
tls_os_sem_acquire(spi_fls->fls_lock, 0);
drv = spi_fls->current_drv;
err = TLS_FLS_STATUS_OK;
err = drv->erase(sector);
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
int tls_spifls_chip_erase(void)
{
int err;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
drv = spi_fls->current_drv;
err = TLS_FLS_STATUS_OK;
err = drv->chip_erase();
return err;
}
int tls_spifls_get_param(u8 type, void *param)
{
int err;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_ERR("the current spi flash driver not installed!\n");
return TLS_FLS_STATUS_ENODRV;
}
if (param == NULL)
{
return TLS_FLS_STATUS_EINVAL;
}
tls_os_sem_acquire(spi_fls->fls_lock, 0);
drv = spi_fls->current_drv;
err = TLS_FLS_STATUS_OK;
switch (type)
{
case TLS_FLS_PARAM_TYPE_ID:
*((u32 *) param) = drv->id;
break;
case TLS_FLS_PARAM_TYPE_SIZE:
*((u32 *) param) = drv->total_size;
break;
case TLS_FLS_PARAM_TYPE_PAGE_SIZE:
*((u32 *) param) = drv->page_size;
break;
case TLS_FLS_PARAM_TYPE_PROG_SIZE:
*((u32 *) param) = drv->program_size;
break;
case TLS_FLS_PARAM_TYPE_SECTOR_SIZE:
*((u32 *) param) = drv->sector_size;
break;
default:
TLS_DBGPRT_WARNING("invalid parameter ID!\n");
err = TLS_FLS_STATUS_EINVAL;
break;
}
tls_os_sem_release(spi_fls->fls_lock);
return err;
}
int tls_spifls_drv_register(struct tls_fls_drv *fls_drv)
{
u32 cpu_sr;
struct tls_fls_drv *drv;
if (fls_drv == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EINVAL;
}
dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
{
if (drv->id == fls_drv->id)
{
TLS_DBGPRT_WARNING
("corresponding spi flash driver has registered!\n");
return TLS_FLS_STATUS_EEXIST;
}
}
cpu_sr = tls_os_set_critical();
dl_list_add_tail((struct dl_list *) &spi_fls->fls_drvs,
(struct dl_list *) &fls_drv->drv_list);
tls_os_release_critical(cpu_sr);
TLS_DBGPRT_FLASH_INFO("the spi flash driver is registered successfully!\n");
return TLS_FLS_STATUS_OK;
}
int tls_spifls_drv_unregister(struct tls_fls_drv *fls_drv)
{
TLS_DBGPRT_WARNING
("unregister spi flash driver operation is not supported!\n");
return TLS_FLS_STATUS_EPERM;
}
int tls_spifls_probe(void)
{
int err;
u32 id;
struct tls_fls_drv *drv;
if (spi_fls == NULL)
{
TLS_DBGPRT_ERR("flash driver module not beed installed!\n");
return TLS_FLS_STATUS_EPERM;
}
if (spi_fls->current_drv != NULL)
{
TLS_DBGPRT_ERR("the current spi flash has fount the matched driver!\n");
return TLS_FLS_STATUS_EBUSY;
}
TLS_DBGPRT_FLASH_INFO("try to read the current spi flash ID.\n");
err = tls_spifls_read_id(&id);
if (err != TLS_FLS_STATUS_OK)
{
return err;
}
TLS_DBGPRT_FLASH_INFO("current spi flash ID - 0x%x.\n", id);
dl_list_for_each(drv, &spi_fls->fls_drvs, struct tls_fls_drv, drv_list)
{
err = drv->probe(id);
if (err != TLS_FLS_STATUS_OK)
{
return err;
}
tls_spi_setup(drv->mode, drv->cs_active, drv->clock);
TLS_DBGPRT_FLASH_INFO("matched the spi flash driver.\n");
spi_fls->current_drv = drv;
break;
}
if (spi_fls->current_drv == NULL)
{
TLS_DBGPRT_WARNING("not found the matched spi flash driver!\n");
return TLS_FLS_STATUS_ENODRV;
}
return TLS_FLS_STATUS_OK;
}
int tls_spifls_init(void)
{
struct tls_fls *fls;
int err;
if (spi_fls != NULL)
{
TLS_DBGPRT_ERR("flash driver module has been installed!\n");
return TLS_FLS_STATUS_EBUSY;
}
fls = (struct tls_fls *) tls_mem_alloc(sizeof(struct tls_fls));
if (fls == NULL)
{
TLS_DBGPRT_ERR("allocate @spi_fls fail!\n");
return TLS_FLS_STATUS_ENOMEM;
}
memset(fls, 0, sizeof(*fls));
dl_list_init((struct dl_list *) &fls->fls_drvs);
err = tls_os_sem_create(&fls->fls_lock, 1);
if (err != TLS_OS_SUCCESS)
{
tls_mem_free(fls);
TLS_DBGPRT_ERR("create semaphore @fls_lock fail!\n");
return TLS_FLS_STATUS_ENOMEM;
}
spi_fls = fls;
tls_spifls_drv_install();
return TLS_FLS_STATUS_OK;
}
int tls_spifls_exit(void)
{
TLS_DBGPRT_FLASH_INFO("Not support flash driver module uninstalled!\n");
return TLS_FLS_STATUS_EPERM;
}
+307
View File
@@ -0,0 +1,307 @@
/**
* @file wm_fls_gd25qxx.c
*
* @brief gd25qxx flash Driver Module
*
* @author dave
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include <stdlib.h>
#include "wm_type_def.h"
#include "wm_flash.h"
#include "wm_hostspi.h"
#include "wm_fls_gd25qxx.h"
#include "wm_debug.h"
#include "wm_gpio.h"
static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len);
static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len);
static int tls_spifls_drv_page_write(u32 page, u8 * buf);
static int tls_spifls_drv_erase(u32 sector);
static int tls_spifls_drv_chip_erase(void);
static int tls_spifls_drv_probe(u32 id);
static void tls_spifls_drv_remove(void);
static struct tls_fls_drv exspi_fls = {
.drv_list = {NULL, NULL},
.clock = SPI_SCLK,
.mode = TLS_SPI_MODE_0,
.cs_active = TLS_SPI_CS_LOW,
.flags = 0,
.read = tls_spifls_drv_read,
.fast_read = tls_spifls_drv_fast_read,
.page_write = tls_spifls_drv_page_write,
.erase = tls_spifls_drv_erase,
.chip_erase = tls_spifls_drv_chip_erase,
.probe = tls_spifls_drv_probe,
.remove = tls_spifls_drv_remove
};
static struct tls_fls_drv *exspifls_drv = NULL;
static unsigned int swap32(unsigned int v)
{
return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
((v & 0xff0000) >> 8) | (v >> 24);
}
static int tls_spifls_drv_write_enable(void)
{
u8 cmd;
int err;
cmd = EXSPIFLASH_WRITE_ENABLE;
err = tls_spi_write((const u8 *) &cmd, 1);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_wait_write_enable(void)
{
u8 cmd;
u8 sr;
int err;
cmd = EXSPIFLASH_READ_SR1;
sr = 0;
do
{
err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
if (sr & FLASH_STATUS_WEL)
{
break;
}
}
while (1);
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_wait_flash_ready(void)
{
u8 cmd;
u8 sr;
int err;
cmd = EXSPIFLASH_READ_SR1;
sr = 0;
do
{
err = tls_spi_read_with_cmd((const u8 *) &cmd, 1, &sr, 1);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
if ((sr & FLASH_STATUS_BUSY) == 0x00)
{
break;
}
}
while (1);
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_read(u32 addr, u8 * buf, u32 len)
{
u32 cmd;
int err;
cmd = 0;
cmd |= EXSPIFLASH_DATA_READ;
cmd |= swap32(addr) & 0xffffff00;
err = tls_spi_read_with_cmd((const u8 *) &cmd, 4, buf, len);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_fast_read(u32 addr, u8 * buf, u32 len)
{
return TLS_FLS_STATUS_ENOSUPPORT;
}
static int tls_spifls_drv_page_write(u32 page, u8 * buf)
{
u32 cmd;
int err;
err = tls_spifls_drv_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
err = tls_spifls_drv_wait_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
cmd = 0;
cmd |= EXSPIFLASH_PAGE_PROGRAM;
cmd |= swap32(page * exspifls_drv->page_size) & 0xffffff00;
err = tls_spi_write_with_cmd((const u8 *) &cmd, 4, (const u8 *) buf,
exspifls_drv->page_size);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
err = tls_spifls_drv_wait_flash_ready();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_erase(u32 sector)
{
u32 cmd;
int err;
err = tls_spifls_drv_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
err = tls_spifls_drv_wait_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
cmd = 0;
cmd |= EXSPIFLASH_SECTOR_ERASE;
cmd |= swap32(sector * exspifls_drv->sector_size) & 0xffffff00;
err = tls_spi_write((const u8 *) &cmd, 4);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
tls_os_time_delay(6);
err = tls_spifls_drv_wait_flash_ready();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_chip_erase(void)
{
u8 cmd;
int err;
err = tls_spifls_drv_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
err = tls_spifls_drv_wait_write_enable();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
cmd = EXSPIFLASH_CHIP_ERASE;
err = tls_spi_write((const u8 *) &cmd, 1);
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
err = tls_spifls_drv_wait_flash_ready();
if (err != TLS_SPI_STATUS_OK)
{
return TLS_FLS_STATUS_EIO;
}
return TLS_FLS_STATUS_OK;
}
static int tls_spifls_drv_probe(u32 id)
{
// int i = 0;
if (!id)
{
return TLS_FLS_STATUS_EINVAL;
}
exspi_fls.id = id;
if ((id>>16)&0xFF)
{
exspi_fls.total_size = 1 << (id>>16);
}else{
exspi_fls.total_size = FLASH_TOTAL_SIZE; /*1MByte*/
}
exspi_fls.page_size = PAGE_SIZE;
exspi_fls.program_size = PROGRAM_SIZE;
exspi_fls.sector_size = SECTOR_SIZE;
exspifls_drv = &exspi_fls;
return TLS_FLS_STATUS_OK;
}
static void tls_spifls_drv_remove(void)
{
exspifls_drv = NULL;
}
/**
* @brief This function is used to install gd25qxx driver.
*
* @param[in] None
*
* @retval TLS_FLS_STATUS_OK if write flash success
* @retval TLS_FLS_STATUS_EPERM if flash struct point is null
* @retval TLS_FLS_STATUS_ENODRV if flash driver is not installed
* @retval TLS_FLS_STATUS_EINVAL if argument is invalid
* @retval TLS_FLS_STATUS_EIO if io error
* @retval TLS_FLS_STATUS_EEXIST if driver is already existed
*
* @note None
*/
int tls_spifls_drv_install(void)
{
int err;
extern int tls_spifls_probe(void);
extern int tls_spifls_drv_register(struct tls_fls_drv *fls_drv);␍
err = tls_spifls_drv_register((struct tls_fls_drv *) &exspi_fls);
if (err == TLS_FLS_STATUS_EEXIST)
{
return err;
}
TLS_DBGPRT_INFO("register the spi flash driver - %d.\n", err);
err = tls_spifls_probe();
TLS_DBGPRT_INFO("probe spi flash - %d.\n", err);
return err;
}
+411
View File
@@ -0,0 +1,411 @@
/**
* @file wm_gpio.c
*
* @brief GPIO Driver Module
*
* @author dave
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include "wm_gpio.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_osal.h"
#include "tls_common.h"
struct gpio_irq_context{
tls_gpio_irq_callback callback;
void *arg;
};
static struct gpio_irq_context gpio_context[WM_IO_PB_30 - WM_IO_PA_00 + 1] = {{0,0}};
void GPIOA_IRQHandler(void)
{
u8 i = 0;
u8 found = 0;
u32 reg = 0;
reg = tls_reg_read32(HR_GPIO_MIS);
for (i = 0; i <= WM_IO_PA_15; i++)
{
if (reg & BIT(i))
{
found = 1;
break;
}
}
if (found)
{
if (NULL != gpio_context[i].callback)
gpio_context[i].callback(gpio_context[i].arg);
}
return;
}
void GPIOB_IRQHandler(void)
{
u8 i = 0;
u8 found = 0;
u32 reg = 0;
reg = tls_reg_read32(HR_GPIO_MIS + TLS_IO_AB_OFFSET);
for (i = WM_IO_PB_00; i <= WM_IO_PB_31; i++)
{
if (reg & BIT(i - WM_IO_PB_00))
{
found = 1;
break;
}
}
if (found)
{
if (NULL != gpio_context[i].callback)
gpio_context[i].callback(gpio_context[i].arg);
}
return;
}
/**
* @brief This function is used to config gpio function
*
* @param[in] gpio_pin gpio pin num
* @param[in] dir gpio direction
* @param[in] attr gpio attribute
*
* @return None
*
* @note
* All gpio's attribute can only be set as WM_GPIO_ATTR_FLOATING or WM_GPIO_ATTR_PULLHIGH on W600/W60X.
*/
void tls_gpio_cfg(enum tls_io_name gpio_pin, enum tls_gpio_dir dir, enum tls_gpio_attr attr)
{
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
/* enable gpio function */
tls_io_cfg_set(gpio_pin, WM_IO_OPT5_GPIO);
/* gpio direction */
if (WM_GPIO_DIR_OUTPUT == dir)
{
tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) | BIT(pin)); /* 1 set output */
}
else if (WM_GPIO_DIR_INPUT == dir)
{
tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin))); /* 0 set input */
}
/* gpio pull attribute */
if (WM_GPIO_ATTR_FLOATING == attr)
{
tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) | BIT(pin)); /* 1 disable pull */
}
else if (WM_GPIO_ATTR_PULLHIGH == attr)
{
tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin))); /* 0 enable pull */
}
}
/**
* @brief This function is used to read gpio status
*
* @param[in] gpio_pin gpio pin num
*
* @retval 0 low level
* @retval 1 high level
*
* @note None
*/
u8 tls_gpio_read(enum tls_io_name gpio_pin)
{
u32 reg_en;
u32 reg;
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset);
tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin));
reg = tls_reg_read32(HR_GPIO_DATA + offset);
tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en);
if(reg & (0x1 << pin))
return 1;
else
return 0;
}
/**
* @brief This function is used to modify gpio status
*
* @param[in] gpio_pin gpio pin num
* @param[in] value power level
* 0: low level
* 1: high level
*
* @return None
*
* @note None
*/
void tls_gpio_write(enum tls_io_name gpio_pin, u8 value)
{
u32 cpu_sr = 0;
u32 reg;
u32 reg_en;
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
cpu_sr = tls_os_set_critical();
reg_en = tls_reg_read32(HR_GPIO_DATA_EN + offset);
tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en | (1 << pin));
reg = tls_reg_read32(HR_GPIO_DATA + offset);
if(value)
tls_reg_write32(HR_GPIO_DATA + offset, reg | (1 << pin)); /* write high */
else
tls_reg_write32(HR_GPIO_DATA + offset, reg & (~(1 << pin)));/* write low */
tls_reg_write32(HR_GPIO_DATA_EN + offset, reg_en);
tls_os_release_critical(cpu_sr);
}
/**
* @brief This function is used to config gpio interrupt
*
* @param[in] gpio_pin gpio pin num
* @param[in] mode interrupt trigger type
*
* @return None
*
* @note None
*/
void tls_gpio_irq_enable(enum tls_io_name gpio_pin, enum tls_gpio_irq_trig mode)
{
u32 reg;
u8 pin;
u16 offset;
u8 vec_no;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
vec_no = GPIOB_INT;
}
else
{
pin = gpio_pin;
offset = 0;
vec_no = GPIO_INT;
}
switch(mode)
{
case WM_GPIO_IRQ_TRIG_RISING_EDGE:
reg = tls_reg_read32(HR_GPIO_IS + offset);
reg &= (~(0x1 << pin));
tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */
reg = tls_reg_read32(HR_GPIO_IBE + offset);
reg &= (~(0x1 << pin));
tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */
reg = tls_reg_read32(HR_GPIO_IEV + offset);
reg |= (0x1 << pin);
tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 1 rising edge trigger */
break;
case WM_GPIO_IRQ_TRIG_FALLING_EDGE:
reg = tls_reg_read32(HR_GPIO_IS + offset);
reg &= (~(0x1 << pin));
tls_reg_write32(HR_GPIO_IS + offset, reg); /* 0 edge trigger */
reg = tls_reg_read32(HR_GPIO_IBE + offset);
reg &= (~(0x1 << pin));
tls_reg_write32(HR_GPIO_IBE + offset, reg); /* 0 edge trigger */
reg = tls_reg_read32(HR_GPIO_IEV + offset);
reg &= (~(0x1 << pin));
tls_reg_write32(HR_GPIO_IEV + offset, reg); /* 0 falling edge trigger */
break;
case WM_GPIO_IRQ_TRIG_DOUBLE_EDGE:
reg = tls_reg_read32(HR_GPIO_IS + offset);
tls_reg_write32(HR_GPIO_IS + offset, reg & (~(0x1 << pin))); /* 0 edge trigger */
reg = tls_reg_read32(HR_GPIO_IBE + offset);
tls_reg_write32(HR_GPIO_IBE + offset, reg | (0x1 << pin)); /* 1 double edge trigger */
break;
case WM_GPIO_IRQ_TRIG_HIGH_LEVEL:
reg = tls_reg_read32(HR_GPIO_IS + offset);
tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */
reg = tls_reg_read32(HR_GPIO_IEV + offset);
tls_reg_write32(HR_GPIO_IEV + offset, reg | (0x1 << pin)); /* 1 high level trigger */
break;
case WM_GPIO_IRQ_TRIG_LOW_LEVEL:
reg = tls_reg_read32(HR_GPIO_IS + offset);
tls_reg_write32(HR_GPIO_IS + offset, reg | (0x1 << pin)); /* 1 level trigger */
reg = tls_reg_read32(HR_GPIO_IEV + offset);
tls_reg_write32(HR_GPIO_IEV + offset, reg & (~(0x1 << pin))); /* 0 low level trigger */
break;
}
reg = tls_reg_read32(HR_GPIO_IE + offset);
reg |= (0x1 << pin);
tls_reg_write32(HR_GPIO_IE + offset, reg); /* enable interrupt */
tls_irq_enable(vec_no);
}
/**
* @brief This function is used to disable gpio interrupt
*
* @param[in] gpio_pin gpio pin num
*
* @return None
*
* @note None
*/
void tls_gpio_irq_disable(enum tls_io_name gpio_pin)
{
u32 reg;
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
reg = tls_reg_read32(HR_GPIO_IE + offset);
tls_reg_write32(HR_GPIO_IE + offset, reg & (~(0x1 << pin))); /* disable interrupt */
tls_irq_disable(GPIO_INT);
}
/**
* @brief This function is used to get gpio interrupt status
*
* @param[in] gpio_pin gpio pin num
*
* @retval 0 no interrupt happened
* @retval 1 interrupt happened
*
* @note None
*/
u8 tls_get_gpio_irq_status(enum tls_io_name gpio_pin)
{
u32 reg;
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
reg = tls_reg_read32(HR_GPIO_RIS + offset);
if(reg & (0x1 << pin))
return 1;
else
return 0;
}
/**
* @brief This function is used to clear gpio interrupt flag
*
* @param[in] gpio_pin gpio pin num
*
* @return None
*
* @note None
*/
void tls_clr_gpio_irq_status(enum tls_io_name gpio_pin)
{
u32 reg;
u8 pin;
u16 offset;
if (gpio_pin >= WM_IO_PB_00)
{
pin = gpio_pin - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = gpio_pin;
offset = 0;
}
reg = tls_reg_read32(HR_GPIO_IC + offset);
tls_reg_write32(HR_GPIO_IC + offset, reg | (0x1 << pin)); /* 1 clear interrupt status */
}
/**
* @brief This function is used to register gpio interrupt
*
* @param[in] gpio_pin gpio pin num
* @param[in] callback the gpio interrupt call back function
* @param[in] arg parammeter for the callback
*
* @return None
*
* @note
* gpio callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_gpio_isr_register(enum tls_io_name gpio_pin,
tls_gpio_irq_callback callback,
void *arg)
{
gpio_context[gpio_pin].callback = callback;
gpio_context[gpio_pin].arg = arg;
}
File diff suppressed because it is too large Load Diff
+493
View File
@@ -0,0 +1,493 @@
/**
* @file wm_hspi.c
*
* @brief High speed spi slave Module
*
* @author dave
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wm_hspi.h"
#include "wm_regs.h"
#include "wm_config.h"
#include "wm_mem.h"
#include "wm_osal.h"
#include "wm_irq.h"
#include "lwip/mem.h"
#include "wm_io.h"
#if TLS_CONFIG_HS_SPI
struct tls_slave_hspi g_slave_hspi;
#define SET_BIT(x) (1UL << (x))
void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc);
void hspi_rx_init(struct tls_slave_hspi *hspi)
{
struct tls_hspi_rx_desc *hspi_rx_desc;
int i;
/* set current availble rx desc pointer */
hspi_rx_desc = (struct tls_hspi_rx_desc *) HSPI_RX_DESC_BASE_ADDR;
hspi->curr_rx_desc = hspi_rx_desc;
/* initialize rx descriptor content */
for (i = 0; i < HSPI_RX_DESC_NUM; i++)
{
/* initialize tx descriptors */
if (i < HSPI_RXBUF_NUM)
{
hspi_rx_desc->valid_ctrl = SET_BIT(31);
hspi_rx_desc->buf_addr = HSPI_RXBUF_BASE_ADDR + i * HSPI_RXBUF_SIZE;
}
else
{
/* indicate this descriptor is can't use by hspi */
hspi_rx_desc->valid_ctrl = 0;
/* point to null */
hspi_rx_desc->buf_addr = 0x0;
}
if (i == (HSPI_RX_DESC_NUM - 1))
{
hspi_rx_desc->next_desc_addr = (u32) HSPI_RX_DESC_BASE_ADDR;
}
else
{
hspi_rx_desc->next_desc_addr = (u32) (hspi_rx_desc + 1);
}
hspi_rx_desc++;
}
}
void hspi_tx_init(struct tls_slave_hspi *hspi)
{
struct tls_hspi_tx_desc *hspi_tx_desc;
int i;
hspi_tx_desc = (struct tls_hspi_tx_desc *) HSPI_TX_DESC_BASE_ADDR;
hspi->curr_tx_desc = hspi_tx_desc;
for (i = 0; i < HSPI_TX_DESC_NUM; i++)
{
hspi_tx_desc->valid_ctrl = 0;
hspi_tx_desc->buf_info = 0;
#if HSPI_TX_MEM_MALLOC
hspi_tx_desc->txbuf_addr = NULL;
hspi_tx_desc->buf_addr[0] = 0;
#else
hspi_tx_desc->buf_addr[0] = HSPI_TXBUF_BASE_ADDR + i * HSPI_TXBUF_SIZE;
#endif
hspi_tx_desc->buf_addr[1] = 0;
hspi_tx_desc->buf_addr[2] = 0;
if (i == (HSPI_TX_DESC_NUM - 1))
{
hspi_tx_desc->next_desc_addr = (u32) HSPI_TX_DESC_BASE_ADDR;
}
else
{
hspi_tx_desc->next_desc_addr = (u32) (hspi_tx_desc + 1);
}
hspi_tx_desc++;
}
}
static int slave_spi_rx_data(struct tls_slave_hspi *hspi)
{
struct tls_hspi_rx_desc *rx_desc;
/* get rx descriptor */
rx_desc = hspi->curr_rx_desc;
while (!(rx_desc->valid_ctrl & SET_BIT(31)))
{
if (hspi->rx_data_callback)
hspi->rx_data_callback((char *) rx_desc->buf_addr);
hspi_free_rxdesc(rx_desc);
rx_desc = (struct tls_hspi_rx_desc *) rx_desc->next_desc_addr;
hspi->curr_rx_desc = rx_desc;
}
return 0;
}
void SDIO_RX_IRQHandler(void)
{
struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
#if HSPI_TX_MEM_MALLOC
hspi->txdoneflag = 1;
#endif
if (hspi->tx_data_callback)
hspi->tx_data_callback((char *) hspi->curr_tx_desc->buf_addr);
/* clear interrupt */
tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_UP);
}
void SDIO_TX_IRQHandler(void)
{
struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
//用户模式下,直接给出数据,链表的操作不对外开放,避免造成链表操作错误
if (hspi->ifusermode)
{
slave_spi_rx_data(hspi);
}
else
{
if (hspi->rx_data_callback)
hspi->rx_data_callback((char *) hspi->curr_rx_desc->buf_addr);
}
/* clear interrupt */
tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_DOWN);
}
void SDIO_TX_CMD_IRQHandler(void)
{
struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
if (hspi->rx_cmd_callback)
hspi->rx_cmd_callback((char *) SDIO_CMD_RXBUF_ADDR);
if (hspi->ifusermode) // 用户模式下,数据给出去之后,寄存器由驱动自己操作
{
tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
}
/* clear interrupt */
tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_DOWN);
}
void SPI_HS_IRQHandler(void)
{
printf("spi HS irqhandle\n");
}
void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc)
{
rx_desc->valid_ctrl = SET_BIT(31);
/* 设置hspi/sdio tx enable寄存器,让sdio硬件知道有可用的tx descriptor */
tls_reg_write32(HR_SDIO_TXEN, SET_BIT(0));
}
void hspi_regs_cfg(void)
{
tls_reg_write32(HR_HSPI_CLEAR_FIFO, 0x1); /* Clear data up&down interrput
*/
tls_reg_write32(HR_HSPI_SPI_CFG, 0); /* CPOL=0, CPHA=0, Small-Endian */
tls_reg_write32(HR_HSPI_MODE_CFG, 0x0);
tls_reg_write32(HR_HSPI_INT_MASK, 0x03);
tls_reg_write32(HR_HSPI_INT_STTS, 0x03);
}
void sdio_init_cis(void)
{
tls_reg_write32(FN0_TPL_FUNCID, 0x000C0221);
tls_reg_write32(FN0_TPL_FUNCE, 0x00000422);
tls_reg_write32(FN0_TPL_FUNCE_MAXBLK, 0x04203208);
tls_reg_write32(FN0_TPL_MANFID_MID, 0x53470296);
tls_reg_write32(FN0_TPL_END, 0x000000ff);
tls_reg_write32(FN1_TPL_FUNCID, 0x000C0221);
tls_reg_write32(FN1_TPL_FUNCE, 0x01012a22);
tls_reg_write32(FN1_TPL_FUNCE_VER, 0x00000011);
tls_reg_write32(FN1_TPL_FUNCE_NSN, 0x02000000);
tls_reg_write32(FN1_TPL_FUNCE_CSASIZE, 0x08000300);
tls_reg_write32(FN1_TPL_FUNCE_OCR, 0x00FF8000);
tls_reg_write32(FN1_TPL_FUNCE_MINPWR, 0x010f0a08);
tls_reg_write32(FN1_TPL_FUNCE_STANDBY, 0x00000101);
tls_reg_write32(FN1_TPL_FUNCE_OPTBW, 0x00000000);
tls_reg_write32(FN1_TPL_FUNCE_NTIMEOUT, 0x00000000);
tls_reg_write32(FN1_TPL_FUNCE_AVGPWR, 0x00000000);
tls_reg_write32(FN1_TPL_FUNCE_AVGPWR + 4, 0x00000000);
tls_reg_write32(FN1_TPL_END, 0x000000ff);
}
void hsdio_regs_cfg(void)
{
u32 v;
sdio_init_cis();
tls_reg_write32(HR_SDIO_CIS0, SDIO_CIS0_ADDR - 0x1000);
tls_reg_write32(HR_SDIO_CIS1, SDIO_CIS1_ADDR - 0x2000);
v = tls_reg_read32(HR_SDIO_CIA);
tls_reg_write32(HR_SDIO_CIA, (v & 0xFFFFF000) | 0x232);
/* set sdio ready */
tls_reg_write32(HR_SDIO_PROG, 0x02FD);
}
/**
* @brief This function is used to initial HSPI register.
*
* @param[in] None
*
* @retval 0 success
* @retval other failed
*
* @note When the system is initialized, the function has been called, so users can not call the function.
*/
int tls_slave_spi_init(void)
{
struct tls_slave_hspi *hspi;
hspi = &g_slave_hspi;
memset(hspi, 0, sizeof(struct tls_slave_hspi));
hspi_rx_init(hspi);
hspi_tx_init(hspi);
// tls_set_high_speed_interface_type(HSPI_INTERFACE_SPI);
/* regiseter hspi tx rx cmd interrupt handler */
/* setting hw interrupt module isr enable regiset */
tls_irq_enable(SDIO_TX_DATA_INT);
tls_irq_enable(SDIO_RX_DATA_INT);
tls_irq_enable(SDIO_TX_CMD_INT);
tls_irq_enable(SPI1_INT);
/********************************************
* setting hspi wrapper registers
*********************************************/
/* hspi data down(rx) */
tls_reg_write32(HR_SDIO_TXBD_ADDR, HSPI_RX_DESC_BASE_ADDR);
tls_reg_write32(HR_SDIO_TXBD_LINKEN, 1);
tls_reg_write32(HR_SDIO_TXEN, 1);
/* hspi data up (tx) */
tls_reg_write32(HR_SDIO_RXBD_ADDR, HSPI_TX_DESC_BASE_ADDR);
tls_reg_write32(HR_SDIO_RXBD_LINKEN, 1);
/* hspi cmd down */
tls_reg_write32(HR_SDIO_CMD_ADDR, SDIO_CMD_RXBUF_ADDR);
tls_reg_write32(HR_SDIO_CMD_SIZE, SDIO_CMD_RXBUF_SIZE);
tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
/* enable sdio module register */
tls_reg_write32(HR_SDIO_INT_MASK, 0x00);
return 0;
}
/**
* @brief This function is used to set high speed interface type.
*
* @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO
*
* @return None
*
* @note None
*/
void tls_set_high_speed_interface_type(int type)
{
if (HSPI_INTERFACE_SPI == type)
{
#if 0
#if (HSPI_IO_REUSE_NUM == 0)
tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION1);
tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION1);
tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION1);
tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION1);
tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION1);
#else
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_14))
tls_io_cfg_set(WM_IO_PB_14, WM_IO_OPTION5);
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_15))
tls_io_cfg_set(WM_IO_PB_15, WM_IO_OPTION5);
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16))
tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5);
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_17))
tls_io_cfg_set(WM_IO_PB_17, WM_IO_OPTION5);
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_18))
tls_io_cfg_set(WM_IO_PB_18, WM_IO_OPTION5);
tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION2);
tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION2);
tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION2);
tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION2);
tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION2);
#endif
#endif
hspi_regs_cfg();
}
else if (HSPI_INTERFACE_SDIO == type)
{
#if 0
if(WM_IO_OPTION1 == tls_io_cfg_get(WM_IO_PB_16)) //HSPI_CK,as sdio need close
tls_io_cfg_set(WM_IO_PB_16, WM_IO_OPTION5);
if(WM_IO_OPTION2 == tls_io_cfg_get(WM_IO_PB_08)) //HSPI_CK,as sdio need close
tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION5);
tls_io_cfg_set(WM_IO_PB_08, WM_IO_OPTION3);
tls_io_cfg_set(WM_IO_PB_09, WM_IO_OPTION3);
tls_io_cfg_set(WM_IO_PB_10, WM_IO_OPTION3);
tls_io_cfg_set(WM_IO_PB_11, WM_IO_OPTION3);
tls_io_cfg_set(WM_IO_PB_12, WM_IO_OPTION3);
#if (SDIO_IO_REUSE_NUM == 0)
tls_io_cfg_set(WM_IO_PA_06, WM_IO_OPTION3);
#elif (SDIO_IO_REUSE_NUM == 1)
tls_io_cfg_set(WM_IO_PB_07, WM_IO_OPTION3);
#else
tls_io_cfg_set(WM_IO_PB_13, WM_IO_OPTION4);
#endif
#endif
hsdio_regs_cfg();
}
}
/**
* @brief This function is used to enable or disable user mode.
*
* @param[in] ifenable TRUE or FALSE
*
* @return None
*
* @note If the user enables the user mode, RICM instruction in the system will not be used by SPI.
* If the user wants to use the SPI interface as other use, need to enable the user mode.
* This function must be called before the register function.
*/
void tls_set_hspi_user_mode(u8 ifenable)
{
struct tls_slave_hspi *hspi = &g_slave_hspi;
hspi->ifusermode = ifenable;
if (ifenable)
{
hspi->rx_cmd_callback = NULL;
hspi->rx_data_callback = NULL;
hspi->tx_data_callback = NULL;
}
}
/**
* @brief This function is used to register hspi rx command interrupt.
*
* @param[in] rx_cmd_callback is the hspi rx interrupt call back function.
*
* @return None
*
* @note None
*/
void tls_hspi_rx_cmd_callback_register(s16(*rx_cmd_callback) (char *buf))
{
g_slave_hspi.rx_cmd_callback = rx_cmd_callback;
}
/**
* @brief This function is used to register hspi rx data interrupt.
*
* @param[in] rx_data_callback is the hspi rx interrupt call back function.
*
* @return None
*
* @note None
*/
void tls_hspi_rx_data_callback_register(s16(*rx_data_callback) (char *buf))
{
g_slave_hspi.rx_data_callback = rx_data_callback;
}
/**
* @brief This function is used to register hspi tx data interrupt.
*
* @param[in] tx_data_callback is the hspi tx interrupt call back function.
*
* @return None
*
* @note None
*/
void tls_hspi_tx_data_callback_register(s16(*tx_data_callback) (char *buf))
{
g_slave_hspi.tx_data_callback = tx_data_callback;
}
/**
* @brief This function is used to transfer data.
*
* @param[in] txbuf is a buf for saving user data.
* @param[in] len is the data length.
*
* @retval transfer data len success
* @retval 0 failed
*
* @note None
*/
int tls_hspi_tx_data(char *txbuf, int len)
{
struct tls_hspi_tx_desc *tx_desc;
int totallen = len;
int txlen;
if (NULL == txbuf || len <= 0 || len > (HSPI_TXBUF_SIZE * HSPI_TX_DESC_NUM))
{
printf("\nhspi tx param error\n");
return 0;
}
tx_desc = g_slave_hspi.curr_tx_desc;
while (1)
{
// printf("---\n");
if ((tx_desc->valid_ctrl & SET_BIT(31)) == 0)
break;
tls_os_time_delay(1);
}
while (!(tx_desc->valid_ctrl & SET_BIT(31)))
{
txlen = (totallen > HSPI_TXBUF_SIZE) ? HSPI_TXBUF_SIZE : totallen;
#if HSPI_TX_MEM_MALLOC
if (tx_desc->txbuf_addr != NULL)
{
printf("\nhspi txbuf not null,error %x\n", tx_desc->txbuf_addr);
if (tx_desc->txbuf_addr == tx_desc->buf_addr[0])
{
mem_free((void *) tx_desc->txbuf_addr);
tx_desc->txbuf_addr = NULL;
}
else // 不应该出现
{
printf("\nhspi tx mem error\n");
break;
}
}
tx_desc->txbuf_addr = (u32) mem_malloc(txlen + 1);
if (NULL == tx_desc->txbuf_addr)
{
printf("\nhspi tx data malloc error\n");
break;
}
tx_desc->buf_addr[0] = tx_desc->txbuf_addr;
#endif
MEMCPY((char *) tx_desc->buf_addr[0], txbuf, txlen);
tx_desc->buf_info = txlen << 12;
tx_desc->valid_ctrl = SET_BIT(31);
tls_reg_write32(HR_SDIO_RXEN, 0x01);
tx_desc = (struct tls_hspi_tx_desc *) tx_desc->next_desc_addr;
g_slave_hspi.curr_tx_desc = tx_desc;
totallen -= txlen;
if (totallen <= 0)
break;
}
return (len - totallen);
}
#endif
+319
View File
@@ -0,0 +1,319 @@
/**************************************************************************//**
* @file wm_i2c.c
* @author
* @version
* @date
* @brief
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wm_regs.h"
#include "wm_i2c.h"
#include "wm_cpu.h"
#include "wm_irq.h"
#define I2C_FREQ_MAX (400000)
#define I2C_FREQ_MIN (100000)
#define I2C_WRITE (0x80)
#define I2C_READ (0x00)
typedef struct {
uint8_t addr;
uint8_t dev_addr;
uint8_t state;
uint8_t *buf;
uint16_t len;
uint16_t cnt;
uint8_t cmd;
void (*transfer_done)(void);
} i2c_desc;
enum {
START,
RESTART,
TRANSMIT,
PRERECEIVE,
RECEIVE,
STOP,
DONE,
IDLE,
};
static i2c_desc i2c_transfer;
void tls_i2c_init(u32 freq)
{
u32 div = 0;
tls_sys_clk clk;
if (freq < I2C_FREQ_MIN)
{
freq = I2C_FREQ_MIN;
}
else if (freq > I2C_FREQ_MAX)
{
freq = I2C_FREQ_MAX;
}
tls_sys_clk_get(&clk);
div = (clk.apbclk * 1000000)/(5 * freq) - 1;
tls_reg_write32(HR_I2C_PRER_LO, div & 0xff);
tls_reg_write32(HR_I2C_PRER_HI, (div>>8) & 0xff);
/** enable I2C | Disable Int*/
tls_reg_write32(HR_I2C_CTRL, I2C_CTRL_INT_DISABLE | I2C_CTRL_ENABLE);
tls_irq_enable(I2C_IRQn);
}
/**
* @brief send stop signal
*
*/
void tls_i2c_stop(void)
{
tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STO);
while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP);
}
/**
* @brief waiting for ack signal
* @retval
* - \ref WM_FAILED
* - \ref WM_SUCCESS
*/
int tls_i2c_wait_ack(void)
{
u16 errtime=0;
u32 value;
while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP);
value = tls_reg_read32(HR_I2C_CR_SR);
while(value & I2C_SR_NAK)
{
errtime ++;
if(errtime > 512)
{
printf("wait ack err\n");
tls_i2c_stop();
return WM_FAILED;
}
value = tls_reg_read32(HR_I2C_CR_SR);
}
return WM_SUCCESS;
}
/**
* @brief writes the data to data register of I2C module
* when \ifstart one the start signal will be sent followed by the \data
* when \ifstart zero only the \data will be send
* @param[in] data the data will be write to the data register of I2C module
* @param[in] ifstart when one send start signal, when zero don't
* @retval
*
*/
void tls_i2c_write_byte(u8 data,u8 ifstart)
{
tls_reg_write32(HR_I2C_TX_RX, data);
if(ifstart)
tls_reg_write32(HR_I2C_CR_SR, I2C_CR_STA | I2C_CR_WR);
else
tls_reg_write32(HR_I2C_CR_SR, I2C_CR_WR);
while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP);
}
/**
* @brief get the data stored in data register of I2C module
* @param[in] ifack when one send ack after reading the data register,when zero don't
* @param[in] ifstop when one send stop signal after read, when zero do not send stop
* @retval the received data
*/
u8 tls_i2c_read_byte(u8 ifack,u8 ifstop)
{
u8 data;
u32 value = I2C_CR_RD;
if(!ifack)
value |= I2C_CR_NAK;
if(ifstop)
value |= I2C_CR_STO;
tls_reg_write32(HR_I2C_CR_SR, value);
/** Waiting finish */
while(tls_reg_read32(HR_I2C_CR_SR) & I2C_SR_TIP);
data = tls_reg_read32(HR_I2C_TX_RX);
return data;
}
/**
* @brief start write through int mode
* @param[in] devaddr the device address
* @param[in] wordaddr when one send stop signal after read, when zero do not send stop
* @param[in] buf the address point where data shoule be stored
* @param[in] len the length of data will be received
* @retval
* - \ref WM_FAILED
* - \ref WM_SUCCESS
*/
int wm_i2c_start_write_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len)
{
if (buf == NULL)
{
return WM_FAILED;
}
I2C->TX_RX = devaddr;
i2c_transfer.dev_addr = devaddr;
i2c_transfer.state = START;
i2c_transfer.cmd = I2C_WRITE;
i2c_transfer.buf = buf;
i2c_transfer.len = len;
i2c_transfer.cnt = 0;
i2c_transfer.addr = wordaddr;
I2C->CR_SR = I2C_CR_STA | I2C_CR_WR;
return WM_SUCCESS;
}
/**
* @brief start read through int mode
* @param[in] devaddr the device address
* @param[in] wordaddr when one send stop signal after read, when zero do not send stop
* @param[in] buf the address point where data shoule be stored
* @param[in] len the length of data will be received
* @retval
* - \ref WM_FAILED
* - \ref WM_SUCCESS
*/
int wm_i2c_start_read_it(uint8_t devaddr, uint8_t wordaddr, uint8_t * buf, uint16_t len)
{
if (buf == NULL)
{
return WM_FAILED;
}
I2C->TX_RX = devaddr;
i2c_transfer.dev_addr = devaddr;
i2c_transfer.state = START;
i2c_transfer.cmd = I2C_READ;
i2c_transfer.buf = buf;
i2c_transfer.len = len;
i2c_transfer.cnt = 0;
i2c_transfer.addr = wordaddr;
I2C->CR_SR = I2C_CR_STA | I2C_CR_WR;
return WM_SUCCESS;
}
/**
* @brief This function is used to register i2c transfer done callback function.
* @param[in] done is the i2c transfer done callback function.
* @retval None
* @note None
*/
void wm_i2c_transfer_done_register(void (*done)(void))
{
i2c_transfer.transfer_done = done;
}
void I2C_IRQHandler(void)
{
int i2c_sr;
i2c_sr = I2C->CR_SR;
I2C->CR_SR = 1;
if (i2c_sr & 0x20)
{
printf("I2C AL lost\r\n");
}
if (i2c_sr & 0x01)
{
if ((i2c_sr & 0x80) == 0)
{
switch(i2c_transfer.state)
{
case START:
I2C->TX_RX = i2c_transfer.addr;
I2C->CR_SR = I2C_CR_WR;
if ((i2c_transfer.cmd & I2C_WRITE) == I2C_WRITE)
{
i2c_transfer.state = TRANSMIT;
}
else
{
i2c_transfer.state = RESTART;
}
break;
case RESTART:
I2C->TX_RX = (i2c_transfer.dev_addr | 0x01);
I2C->CR_SR = (I2C_CR_STA | I2C_CR_WR);
i2c_transfer.state = PRERECEIVE;
break;
case TRANSMIT:
I2C->TX_RX = i2c_transfer.buf[i2c_transfer.cnt++];
I2C->CR_SR = I2C_CR_WR;
if (i2c_transfer.cnt == i2c_transfer.len)
{
i2c_transfer.state = STOP;
}
break;
case PRERECEIVE:
i2c_transfer.state = RECEIVE;
I2C->CR_SR = I2C_CR_RD;
break;
case RECEIVE:
i2c_transfer.buf[i2c_transfer.cnt++] = I2C->TX_RX;
if (i2c_transfer.cnt == (i2c_transfer.len - 1))
{
I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD);
i2c_transfer.state = STOP;
}
else if (i2c_transfer.len == 1)
{
I2C->CR_SR = (I2C_CR_STO | I2C_CR_NAK | I2C_CR_RD);
i2c_transfer.state = DONE;
if (i2c_transfer.transfer_done)
{
i2c_transfer.transfer_done();
}
}
else
{
I2C->CR_SR = I2C_CR_RD;
}
break;
case STOP:
I2C->CR_SR = I2C_CR_STO;
i2c_transfer.state = DONE;
if (i2c_transfer.transfer_done)
{
i2c_transfer.transfer_done();
}
break;
}
}
else
{
if ((i2c_transfer.state == STOP) && i2c_transfer.cmd != I2C_WRITE)
{
i2c_transfer.buf[i2c_transfer.cnt] = I2C->TX_RX;
i2c_transfer.state = DONE;
if (i2c_transfer.transfer_done)
{
i2c_transfer.transfer_done();
}
}
}
}
// if ((i2c_sr & 0x40) == 0)
// {
// i2c_transfer.state = IDLE;
// }
}
/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/
+584
View File
@@ -0,0 +1,584 @@
/**************************************************************************//**
* @file wm_i2s.c
* @author
* @version
* @date
* @brief
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved.
*****************************************************************************/
#define TLS_CONFIG_I2S 1
#if TLS_CONFIG_I2S
#include "wm_i2s.h"
#include "string.h"
#include "wm_debug.h"
#include "wm_irq.h"
#include "wm_config.h"
#include "wm_mem.h"
#define I2S_CLK (160000000)
#define WM_I2S_FIFO_LEN (8)
static tls_i2s_port_t tls_i2s_port;
static void tls_i2s_fill_txfifo(void);
/**
* @brief This function is used to initial i2s port.
* @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options.
* @retval
* - \ref WM_SUCCESS
* - \ref WM_FAILED
*
*/
int tls_i2s_port_init(tls_i2s_options_t *opts)
{
tls_i2s_options_t opt;
tls_i2s_port.regs = I2S;
if(NULL == opts)
{
memset(&opt, 0, sizeof(tls_i2s_options_t));
opt.data_width = I2S_CTRL_DATABIT_16;
opt.format = I2S_CTRL_FORMAT_I2S;
opt.stereo_mono = I2S_CTRL_STERO;
opt.sample_rate = 8000;
opt.tx_en = 1;
tls_i2s_config(&opt);
}
else
{
tls_i2s_config(opts);
}
/* enable i2s interrupt */
NVIC_ClearPendingIRQ(I2S_IRQn);
tls_irq_enable(I2S_INT);
return WM_SUCCESS;
}
/**
* @brief This function is used to initial i2s port.
* @param[in] opts the i2s setting options,if this param is NULL,this function will use the default options.
*
* @retval
*
* @note
*/
void tls_i2s_config(tls_i2s_options_t *opts)
{
tls_i2s_port.regs->CTRL &= ~(I2S_CTRL_FORMAT_MASK | \
I2S_CTRL_DATABIT_MASK | \
I2S_CTRL_STEREO_MONO_MASK);
tls_i2s_port.regs->CTRL = opts->data_width | opts->format | opts->stereo_mono;
if (opts->rx_en)
{
TLS_I2S_RX_ENABLE();
TLS_I2S_RX_FIFO_CLEAR();
}
if (opts->tx_en)
{
TLS_I2S_TX_ENABLE();
TLS_I2S_TX_FIFO_CLEAR();
}
tls_i2s_set_freq(opts->sample_rate);
}
/**
* @brief
* set the frequency of the i2s port.
*
* @param[in] freq
* the required frequency of the i2s module
*
* @retval
*
*/
void tls_i2s_set_freq(uint32_t freq)
{
uint32_t div;
uint32_t reg;
uint8_t width, stereo;
reg = I2S->CTRL;
width = (((reg>>4)&0x03)+1)<<3;
stereo = tls_bitband_read(HR_I2S_CTRL, I2S_CTRL_STEREO_MONO_Pos) ? 1:2;
div = (I2S_CLK + freq * width * stereo)/(freq * width * stereo) - 1;
*(volatile uint32_t *)HR_CLK_I2S_CTL &= ~0xFF00;
*(volatile uint32_t *)HR_CLK_I2S_CTL |= (uint32_t)div<<8;
}
/**
* @brief
* set the frequency of the i2s port.
*
* @param[in] freq
* the required frequency of the i2s module
* @param[in] exclk
* the frequency of the ext clock
*
* @retval
*
* @note
* this function will be called after tls_i2s_port_init function
*/
void wm_i2s_set_freq_exclk(uint32_t freq, uint32_t exclk)
{
uint32_t div;
uint32_t temp;
uint8_t wdwidth, stereo;
temp = I2S->CTRL;
wdwidth = (((temp>>4)&0x03)+1)<<3;
stereo = tls_bitband_read(HR_I2S_CTRL, 22) ? 1:2;
div = (exclk * 2 + freq * wdwidth * stereo)/(2* freq * wdwidth * stereo) - 1;
*(volatile uint32_t *)0x40000718 &= ~0x3FF00;
*(volatile uint32_t *)0x40000718 |= (uint32_t)div<<8;
*(volatile uint32_t *)0x40000718 |= 0x01;
}
void I2S_IRQHandler(void)
{
uint8_t rx_fifocnt;
/** LZC */
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_LZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_LZC_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_LZC);
}
/** RZC */
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RZC_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RZC_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RZC);
}
/** Tx Done*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXDONE_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXDONE);
}
/** TxTH*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXTH_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXTH);
tls_i2s_fill_txfifo();
}
/** TXOV*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXOV_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXOV);
}
/** TXUD*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_TXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_TXUD_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_TXUD);
}
/** Rx Done*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXDONE_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXDONE_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXDONE);
}
/** RxTH */
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXTH_Pos)&& !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXTH_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXTH);
rx_fifocnt = tls_i2s_port.regs->INT_STATUS & I2S_RX_FIFO_CNT_MASK;
if (tls_i2s_port.rx_buf.buf != NULL)
{
while(rx_fifocnt-- > 0)
{
tls_i2s_port.rx_buf.buf[tls_i2s_port.rx_buf.index] = tls_i2s_port.regs->RX;
tls_i2s_port.rx_buf.index++;
}
if (tls_i2s_port.rx_buf.index >= (tls_i2s_port.rx_buf.len))
{
tls_i2s_port.rx_buf.buf = NULL;
tls_i2s_int_config(I2S_INT_MASK_RXTH, 0);
if (tls_i2s_port.rx_callback != NULL)
{
tls_i2s_port.rx_callback(tls_i2s_port.rx_buf.len);
}
tls_i2s_port.rx_buf.index = 0;
}
}
}
/** RXOV*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXOV_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXOV_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXOV);
}
/** RXUD*/
if (tls_bitband_read(HR_I2S_INT_SRC, I2S_FLAG_RXUD_Pos) && !tls_bitband_read(HR_I2S_INT_MASK, I2S_FLAG_RXUD_Pos))
{
tls_reg_write32(HR_I2S_INT_SRC, I2S_FLAG_RXUD);
}
}
/**
* @brief
* This function is used to register i2s rx interrupt.
*
* @param[in] rx_callback
* is the i2s interrupt call back function.
*
* @retval
*
*/
void tls_i2s_rx_register( void (*rx_callback)(u16 len))
{
tls_i2s_port.rx_callback = rx_callback;
}
/**
* @brief
* This function is used to register i2s tx interrupt.
*
* @param[in] tx_callback
* is the i2s interrupt call back function.
*
* @retval
*
*/
void tls_i2s_tx_register(void (* tx_callback)(u16 len))
{
tls_i2s_port.tx_callback = tx_callback;
}
static void tls_i2s_fill_txfifo()
{
s8 fifo_left = 0;
if (tls_i2s_port.tx_buf.index < tls_i2s_port.tx_buf.len)
{
fifo_left = I2S_MAX_RXTXFIFO_LEVEL - ((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4);
while (fifo_left--)
{
tls_i2s_port.regs->TX = *(uint32_t *)(tls_i2s_port.tx_buf.buf + tls_i2s_port.tx_buf.index);
tls_i2s_port.tx_buf.index ++;
}
if(tls_i2s_port.tx_buf.index >= tls_i2s_port.tx_buf.len)
{
while((tls_i2s_port.regs->INT_STATUS & I2S_TX_FIFO_CNT_MASK)>>4);
if(tls_i2s_port.tx_sem)
{
memset(&tls_i2s_port.tx_buf, 0, sizeof(tls_i2s_buf));
tls_os_sem_release(tls_i2s_port.tx_sem);
return;
}
if (tls_i2s_port.tx_callback)
{
tls_i2s_port.tx_callback(tls_i2s_port.tx_buf.len);
}
}
}
}
/**
* @brief
* This function is used to transfer data in blocking mode.
*
* @param[in] buf
* pointer to the transfering data.
*
* @param[in] len
* is the data length.
*
* @retval
*
*/
int tls_i2s_tx_block(uint32_t *buf, uint16_t len)
{
uint8_t err;
err = tls_os_sem_create(&tls_i2s_port.tx_sem, 0);
if (err != TLS_OS_SUCCESS)
{
TLS_DBGPRT_ERR("\ni2s tx sem create fail\n");
return WM_FAILED;
}
TLS_I2S_TX_FIFO_CLEAR();
tls_reg_write32(HR_I2S_INT_SRC, 0x1FF);
NVIC_ClearPendingIRQ(I2S_IRQn);
tls_i2s_port.tx_buf.buf = buf;
tls_i2s_port.tx_buf.len = len;
tls_i2s_port.tx_buf.index = 0;
tls_i2s_set_txth(5);
tls_i2s_int_config(I2S_INT_MASK_TXTH, 1);
TLS_I2S_TX_ENABLE();
TLS_I2S_ENABLE();
tls_os_sem_acquire(tls_i2s_port.tx_sem, 0);
tls_os_sem_delete(tls_i2s_port.tx_sem);
tls_i2s_port.tx_sem = NULL;
TLS_I2S_TX_DISABLE();
return WM_SUCCESS;
}
/**
* @brief
* This function is used to transfer data in non blocking mode.
*
* @param[in] buf
* is a buf for user data.
*
* @param[in] len
* is the data length.
*
* @param[in] tx_callback
* a function pointer,which will be called when the designated data sent
*
* @retval
*
* @note the \ref len in words
*/
int tls_i2s_tx_nonblock(uint32_t *buf, uint16_t len, void (*tx_callback)(u16 len))
{
tls_i2s_port.tx_buf.buf = (uint32_t *)buf;
tls_i2s_port.tx_buf.len = len;
tls_i2s_port.tx_buf.index = 0;
tls_i2s_set_txth(5);
tls_i2s_int_config(I2S_INT_MASK_TXTH, 1);
tls_i2s_tx_register( tx_callback);
TLS_I2S_TX_FIFO_CLEAR();
TLS_I2S_TX_ENABLE();
TLS_I2S_ENABLE();
return WM_SUCCESS;
}
/**
* @brief
* This function is used to receiver data in non blocking mode.
*
* @param[in] buf
* the buffer for storing the received data.
*
* @param[in] len
* the length of the data will be receiving
*
* @param[in] rx_callback
* a function pointer,which will be called when the demanded data have been received
*
* @retval
*
*/
int tls_i2s_rx_nonblock(uint32_t *buf, uint16_t len, void (*rx_callback)(u16 len))
{
tls_i2s_port.rx_buf.buf = buf;
tls_i2s_port.rx_buf.len = len;
tls_i2s_port.rx_buf.index = 0;
tls_i2s_set_rxth(5);
tls_i2s_int_config(I2S_INT_MASK_RXTH, 1);
tls_i2s_rx_register( rx_callback);
TLS_I2S_RX_FIFO_CLEAR();
NVIC_ClearPendingIRQ(I2S_IRQn);
TLS_I2S_RX_ENABLE();
TLS_I2S_ENABLE();
return WM_SUCCESS;
}
/**
* @brief
* This function is used to the tx DMA configuration of the I2S module.
*
* @param[in] dma_channel
* the free dma channel number which returned by calling function tls_dma_request()
*
* @param[in] addr
* point to the data buffer will be sent
*
* @param[in] len
* length of the data to be transfered in bytes
*
* @retval
*/
void tls_i2s_tx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len)
{
struct tls_dma_descriptor DmaDesc;
TLS_I2S_TX_DISABLE();
TLS_I2S_TX_FIFO_CLEAR();
/** Mask i2s txth interrupt*/
tls_i2s_set_txth(4);
tls_i2s_int_config(I2S_INT_MASK_TXTH, 0);
DmaDesc.src_addr = (unsigned int) addr;
DmaDesc.dest_addr = (unsigned int)HR_I2S_TX;
DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
(len << 7);
DmaDesc.valid = TLS_DMA_DESC_VALID;
DmaDesc.next = NULL;
tls_dma_start(dma_channel, &DmaDesc, 0);
}
/**
* @brief
* datas transmit throuth DMA
*
* @param[in] addr
* point to the data buffer will be sent
* @param[in] len
* length of the data to be transfered in bytes
* @param[in] callback
* the callback function when datas transfer finished
*
* @retval
*
* @note the \ref len in bytes
*/
int tls_i2s_tx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback)
{
uint8_t tx_channel;
TLS_I2S_TX_FIFO_CLEAR();
tls_reg_write32(HR_I2S_INT_SRC, 0x1FF);
NVIC_ClearPendingIRQ(I2S_IRQn);
TLS_I2S_TX_FIFO_CLEAR();
tx_channel = tls_dma_request(WM_I2S_TX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_TX) | TLS_DMA_FLAGS_HARD_MODE);
if (tx_channel == 0)
{
return WM_FAILED;
}
if (tls_dma_stop(tx_channel))
{
return WM_FAILED;
}
tls_i2s_tx_dma_config(tx_channel, addr, len);
tls_dma_irq_register(tx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
TLS_I2S_TXDMA_ENABLE();
TLS_I2S_TX_ENABLE();
TLS_I2S_ENABLE();
return WM_SUCCESS;
}
/**
* @brief
* This function is used to the rx DMA configuration of the I2S module.
*
* @param[in] addr
* point to the storge buffer of the received data
*
* @param[in] len
* the storge buffer length in bytes
*
* @retval
*/
void tls_i2s_rx_dma_config(uint8_t dma_channel, uint32_t * addr, uint16_t len)
{
struct tls_dma_descriptor DmaDesc;
tls_i2s_int_config(I2S_INT_MASK_RXTH, 0);
TLS_I2S_RX_DISABLE();
TLS_I2S_RXDMA_DISABLE();
TLS_I2S_RX_FIFO_CLEAR();
/** Mask i2s rxth interrupt*/
tls_i2s_set_rxth(4);
tls_i2s_int_config(I2S_INT_MASK_RXTH, 0);
DmaDesc.src_addr = (int)HR_I2S_RX;
DmaDesc.dest_addr = (int)addr;
DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
(len << 7);
DmaDesc.valid = TLS_DMA_DESC_VALID;
DmaDesc.next = NULL;
tls_dma_start(dma_channel, &DmaDesc, 0);
}
int tls_i2s_rx_dma(uint32_t * addr, uint16_t len, tls_i2s_callback callback)
{
uint8_t rx_channel;
rx_channel = tls_dma_request(WM_I2S_RX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_RX) | TLS_DMA_FLAGS_HARD_MODE);
if (rx_channel == 0)
{
return WM_FAILED;
}
if (tls_dma_stop(rx_channel))
{
return WM_FAILED;
}
tls_i2s_rx_dma_config(rx_channel, addr, len);
tls_dma_irq_register(rx_channel, callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
TLS_I2S_RXDMA_ENABLE();
NVIC_ClearPendingIRQ(I2S_IRQn);
TLS_I2S_RX_ENABLE();
TLS_I2S_ENABLE();
return WM_SUCCESS;
}
#if 1
uint8_t tst_flag = 0;
void tls_i2s_tx_dma_callback()
{
I2S->TX = 0x00;
while(!tls_bitband_read(HR_I2S_INT_SRC, 7));
TLS_I2S_TX_DISABLE();
DMA_CHNLCTRL_REG(WM_I2S_TX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF;
tls_dma_free(WM_I2S_TX_DMA_CHANNEL);
tst_flag = 1;
}
void tls_i2s_rx_dma_callback()
{
TLS_I2S_RX_DISABLE();
DMA_CHNLCTRL_REG(WM_I2S_RX_DMA_CHANNEL) |= DMA_CHNL_CTRL_CHNL_OFF;
tls_dma_free(WM_I2S_RX_DMA_CHANNEL);
tst_flag = 1;
}
void tls_i2s_rx_callback()
{
TLS_I2S_RX_DISABLE();
tst_flag = 1;
}
void tls_i2s_test()
{
uint32_t *ptr = NULL;
uint32_t len;
uint32_t * i2s_tx_test = tls_mem_alloc(1024);
tls_i2s_port.opts.data_width = I2S_CTRL_DATABIT_16;
tls_i2s_port.opts.format = I2S_CTRL_FORMAT_I2S;
tls_i2s_port.opts.tx_en = 1;
tls_i2s_port.opts.sample_rate = 8000;
tls_i2s_port.opts.stereo_mono = I2S_CTRL_STERO;
tls_i2s_port_init(&tls_i2s_port.opts);
if (i2s_tx_test == NULL)
{
return;
}
ptr = i2s_tx_test;
for (len = 0; len < 256; len++)
{
*ptr++ = 0xABCD0200 + len;
}
i2s_tx_test[255] = 0xABCD02FA;
tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback);
while(!tst_flag);
tst_flag = 0;
tls_i2s_tx_dma(i2s_tx_test, 1024,tls_i2s_tx_dma_callback);
while(!tst_flag);
tst_flag = 0;
}
#endif
#endif /** TLS_CONFIG_I2S */
/*** (C) COPYRIGHT 2014 Winner Microelectronics Co., Ltd. ***/
File diff suppressed because it is too large Load Diff
+277
View File
@@ -0,0 +1,277 @@
/**
* @file wm_io.c
*
* @brief IO Driver Module
*
* @author lilm
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include "wm_regs.h"
#include "wm_osal.h"
#include "wm_io.h"
#include "wm_dbg.h"
#include "tls_common.h"
static void io_cfg_option1(enum tls_io_name name)
{
u8 pin;
u16 offset;
if ( (WM_IO_PB_25 == name) || (WM_IO_PB_26 == name) || (WM_IO_PB_29 == name) )
{
TLS_DBGPRT_IO_ERR("io %u have no option1.\r\n", name);
return;
}
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */
tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin)));
tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin)));
return;
}
static void io_cfg_option2(enum tls_io_name name)
{
u8 pin;
u16 offset;
if ( (WM_IO_PB_13 == name) || (WM_IO_PB_27 == name) ||
(WM_IO_PB_31 == name) )
{
TLS_DBGPRT_IO_ERR("io %u have no option2.\r\n", name);
return;
}
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */
tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) & (~BIT(pin)));
tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin));
return;
}
static void io_cfg_option3(enum tls_io_name name)
{
u8 pin;
u16 offset;
if ( (name == WM_IO_PB_19) || (name == WM_IO_PB_20) ||
(name >= WM_IO_PB_23) || (name == WM_IO_PA_00) ||
(name == WM_IO_PA_07) ||
((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) )
{
TLS_DBGPRT_IO_ERR("io %u have no option3.\r\n", name);
return;
}
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */
tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin));
tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) & (~BIT(pin)));
return;
}
static void io_cfg_option4(enum tls_io_name name)
{
u8 pin;
u16 offset;
if( (name == WM_IO_PA_00) || (name == WM_IO_PA_01) ||
(name == WM_IO_PA_06) ||
((name >= WM_IO_PA_13) && (name <= WM_IO_PA_15)) ||
((name >= WM_IO_PB_00) && (name <= WM_IO_PB_02)) ||
(name >= WM_IO_PB_19) )
{
TLS_DBGPRT_IO_ERR("io %u have no option4.\r\n", name);
return;
}
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) | BIT(pin)); /* gpio function */
tls_reg_write32(HR_GPIO_AF_S1 + offset, tls_reg_read32(HR_GPIO_AF_S1 + offset) | BIT(pin));
tls_reg_write32(HR_GPIO_AF_S0 + offset, tls_reg_read32(HR_GPIO_AF_S0 + offset) | BIT(pin));
return;
}
static void io_cfg_option5(enum tls_io_name name)
{
u8 pin;
u16 offset;
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */
return;
}
static void io_cfg_option6(enum tls_io_name name)
{
u8 pin;
u16 offset;
if( ((name >= WM_IO_PB_06)&&(name <= WM_IO_PB_18)) ||
((name >= WM_IO_PB_29)&&(name <= WM_IO_PB_31)))
{
TLS_DBGPRT_IO_ERR("io %u have no option6.\r\n", name);
return;
}
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
tls_reg_write32(HR_GPIO_AF_SEL + offset, tls_reg_read32(HR_GPIO_AF_SEL + offset) & (~BIT(pin))); /* disable gpio function */
tls_reg_write32(HR_GPIO_DIR + offset, tls_reg_read32(HR_GPIO_DIR + offset) & (~BIT(pin)));
tls_reg_write32(HR_GPIO_PULL_EN + offset, tls_reg_read32(HR_GPIO_PULL_EN + offset) & (~BIT(pin)));
return;
}
/**
* @brief This function is used to config io function
*
* @param[in] name io name
* @param[in] option io function option, value is WM_IO_OPT*_*, also is WM_IO_OPTION1-6
*
* @return None
*
* @note None
*/
void tls_io_cfg_set(enum tls_io_name name, u8 option)
{
if (WM_IO_OPTION1 == option)
io_cfg_option1(name);
else if (WM_IO_OPTION2 == option)
io_cfg_option2(name);
else if (WM_IO_OPTION3 == option)
io_cfg_option3(name);
else if (WM_IO_OPTION4 == option)
io_cfg_option4(name);
else if (WM_IO_OPTION5 == option)
io_cfg_option5(name);
else if (WM_IO_OPTION6 == option)
io_cfg_option6(name);
else
TLS_DBGPRT_IO_ERR("invalid io option.\r\n");
return;
}
/**
* @brief This function is used to get io function config
*
* @param[in] name io name
*
* @retval WM_IO_OPTION1~6 Mapping io function
*
* @note None
*/
int tls_io_cfg_get(enum tls_io_name name)
{
u8 pin;
u16 offset;
u32 afsel,afs1,afs0,dir,pullen;
if (name >= WM_IO_PB_00)
{
pin = name - WM_IO_PB_00;
offset = TLS_IO_AB_OFFSET;
}
else
{
pin = name;
offset = 0;
}
afsel = tls_reg_read32(HR_GPIO_AF_SEL + offset);
afs1 = tls_reg_read32(HR_GPIO_AF_S1 + offset);
afs0 = tls_reg_read32(HR_GPIO_AF_S0 + offset);
dir = tls_reg_read32(HR_GPIO_DIR + offset);
pullen = tls_reg_read32(HR_GPIO_PULL_EN + offset);
if(afsel&BIT(pin))
{
if((0==(afs1&BIT(pin))) && (0==(afs0&BIT(pin))))
return WM_IO_OPTION1;
else if((0==(afs1&BIT(pin))) && (afs0&BIT(pin)))
return WM_IO_OPTION2;
else if((afs1&BIT(pin)) && (0==(afs0&BIT(pin))))
return WM_IO_OPTION3;
else if((afs1&BIT(pin)) && (afs0&BIT(pin)))
return WM_IO_OPTION4;
}
else
{
if((!(dir&BIT(pin))) && (pullen&BIT(pin)))
return WM_IO_OPTION6;
else
return WM_IO_OPTION5;
}
return 0;
}
+270
View File
@@ -0,0 +1,270 @@
/**
* @file wm_iouart.c
*
* @brief IO uart Driver Module
*
* @author dave
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include <string.h>
#include "wm_iouart.h"
#include "wm_debug.h"
#include "wm_irq.h"
#include "wm_config.h"
#include "wm_mem.h"
#include "wm_gpio.h"
#include "wm_timer.h"
#if 1//TLS_CONFIG_IOUART
struct tls_io_uart io_uart;
#if !IO_UART_FOR_PRINT
void iouart0_timer_cb(void)
{
int i = 0;
static u8 ch = 0;
// if(io_uart.ifrx)
{
if (0 == io_uart.bitnum) // 起始位
{
io_uart.bit[io_uart.bitcnt] = tls_gpio_read(IO_UART_RX);
if (io_uart.bit[io_uart.bitcnt++] != 0)
{
io_uart.bitcnt = 0;
tls_timer_stop(io_uart.timerid);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
return;
}
// if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM)
{
io_uart.bitcnt = 0;
io_uart.bitnum ++;
ch = 0;
}
}
else if (io_uart.bitnum >= 1 && io_uart.bitnum <= 8) // 数据位
{
io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX);
if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM)
{
for(i=0; i<(IO_UART_ONEBITE_SAMPLE_NUM-1); i++)
{
if(io_uart.bit[i] != io_uart.bit[i+1])
{
io_uart.bitcnt = 0;
io_uart.bitnum = 0;
tls_timer_stop(io_uart.timerid);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
return;
}
}
if(io_uart.bit[0])
{
ch |= (1 << (io_uart.bitnum - 1));
}
io_uart.bitnum ++;
io_uart.bitcnt = 0;
}
}
else if (9 == io_uart.bitnum) // 停止位
{
io_uart.bit[io_uart.bitcnt++] = tls_gpio_read(IO_UART_RX);
if(io_uart.bitcnt == IO_UART_ONEBITE_SAMPLE_NUM)
{
if(io_uart.bit[i] != io_uart.bit[i+1])
{
io_uart.bitcnt = 0;
io_uart.bitnum = 0;
tls_timer_stop(io_uart.timerid);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
return;
}
}
if(io_uart.bit[0] == 0)
{
io_uart.bitcnt = 0;
io_uart.bitnum = 0;
tls_timer_stop(io_uart.timerid);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
return;
}
io_uart.recv.buf[io_uart.recv.head] = ch;
io_uart.recv.head =(io_uart.recv.head + 1) & (TLS_IO_UART_RX_BUF_SIZE -1);
io_uart.bitnum = 0;
io_uart.bitcnt = 0;
ch = 0;
io_uart.ifrx = 0;
tls_timer_stop(io_uart.timerid);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
}
}
}
void iouart0_gpio_isr_callback(void *context)
{
u16 ret;
ret = tls_get_gpio_irq_status(IO_UART_RX);
if(ret)
{
tls_clr_gpio_irq_status(IO_UART_RX);
ret = tls_gpio_read(IO_UART_RX);
if(ret == 0)
{
io_uart.ifrx = 1;
tls_gpio_irq_disable(IO_UART_RX);
tls_timer_start(io_uart.timerid);
}
}
}
#endif
void iouart_tx_byte(u8 datatoSend)
{
u8 i, tmp;
u32 cpu_sr = 0;
cpu_sr = tls_os_set_critical(); // 发送一个byte的过程中不能被打断,否则可能会有错误码
/* Start bit */
tls_gpio_write(IO_UART_TX, 0);
tls_delay_via_timer(io_uart.timercnt+1, 0);
for (i = 0; i < 8; i++)
{
tmp = (datatoSend >> i) & 0x01;
if (tmp == 0)
{
tls_gpio_write(IO_UART_TX, 0);
}
else
{
tls_gpio_write(IO_UART_TX, 1);
}
tls_delay_via_timer(io_uart.timercnt+1, 0);
}
tls_gpio_write(IO_UART_TX, 1);
tls_delay_via_timer(io_uart.timercnt+1, 0);
tls_os_release_critical(cpu_sr);
}
int tls_iouart_init(int bandrate)
{
char *bufrx;
memset(&io_uart, 0, sizeof(struct tls_io_uart));
#if !IO_UART_FOR_PRINT
bufrx = tls_mem_alloc(TLS_IO_UART_RX_BUF_SIZE);
if (!bufrx)
return WM_FAILED;
memset(bufrx, 0, TLS_IO_UART_RX_BUF_SIZE);
io_uart.recv.buf = (u8 *) bufrx;
io_uart.recv.head = 0;
io_uart.recv.tail = 0;
#endif
tls_gpio_cfg(IO_UART_TX, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_write(IO_UART_TX, 1);
tls_gpio_cfg(IO_UART_RX, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
tls_gpio_isr_register(IO_UART_RX, iouart0_gpio_isr_callback, NULL);
tls_gpio_irq_enable(IO_UART_RX, WM_GPIO_IRQ_TRIG_LOW_LEVEL);
io_uart.timercnt = 1000000 / bandrate;
#if !IO_UART_FOR_PRINT
struct tls_timer_cfg timer_cfg;
timer_cfg.unit = TLS_TIMER_UNIT_US;
timer_cfg.timeout = io_uart.timercnt/IO_UART_ONEBITE_SAMPLE_NUM;
timer_cfg.is_repeat = 1;
timer_cfg.callback = (tls_timer_irq_callback)iouart0_timer_cb;
timer_cfg.arg = NULL;
io_uart.timerid = tls_timer_create(&timer_cfg);
#endif
return WM_SUCCESS;
}
int tls_iouart_destroy(void)
{
tls_gpio_irq_disable(IO_UART_RX);
tls_timer_destroy(io_uart.timerid);
io_uart.timerid = 0xFF;
tls_mem_free(io_uart.recv.buf);
return WM_SUCCESS;
}
int tls_iouart_read(u8 * buf, int bufsize)
{
int data_cnt, buflen, bufcopylen;
if (NULL == buf)
return WM_FAILED;
data_cnt =
CIRC_CNT(io_uart.recv.head, io_uart.recv.tail, TLS_IO_UART_RX_BUF_SIZE);
if (data_cnt >= bufsize)
{
buflen = bufsize;
}
else
{
buflen = data_cnt;
}
if ((io_uart.recv.tail + buflen) > TLS_IO_UART_RX_BUF_SIZE)
{
bufcopylen = (TLS_IO_UART_RX_BUF_SIZE - io_uart.recv.tail);
MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, bufcopylen);
MEMCPY(buf + bufcopylen, io_uart.recv.buf, buflen - bufcopylen);
}
else
{
MEMCPY(buf, io_uart.recv.buf + io_uart.recv.tail, buflen);
}
io_uart.recv.tail = (io_uart.recv.tail + buflen) & (TLS_IO_UART_RX_BUF_SIZE - 1);
return buflen;
}
int tls_iouart_write(u8 * buf, int bufsize)
{
if (NULL == buf || bufsize <= 0 || 1 == io_uart.ifrx)
return WM_FAILED;
io_uart.iftx = 1;
while (bufsize)
{
iouart_tx_byte(*buf);
bufsize--;
buf++;
}
io_uart.iftx = 0;
return WM_SUCCESS;
}
int tls_iouart_output_char(int ch)
{
if(ch == '\n')
iouart_tx_byte('\r');
iouart_tx_byte((char)ch);
return ch;
}
#endif //TLS_CONFIG_IOUART
+149
View File
@@ -0,0 +1,149 @@
/**
* @file wm_irq.c
*
* @brief interupt driver module
*
* @author dave
*
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_config.h"
#include "wm_mem.h"
void tls_irq_handler_dummy(void *data)
{
}
tls_irq_handler_t *intr_handler_vect[INTR_CNT];
u8 intr_counter;
/**
* @brief This function is used to initial system interrupt.
*
* @param[in] None
*
* @return None
*
* @note None
*/
void tls_irq_init(void)
{
#if 0
int i;
for (i = 0; i < INTR_CNT; i++)
{
intr_handler_vect[i].handler = tls_irq_handler_dummy;
intr_handler_vect[i].data = NULL;
intr_handler_vect[i].name = "intr_dummy";
intr_handler_vect[i].counter = 0;
}
#endif
intr_counter = 0;
/* initailize VIC */
tls_reg_write32(HR_VIC_INT_SELECT, 0);
tls_reg_write32(HR_VIC_VECT_ENABLE, 0); /* disable vector interrupt */
tls_reg_write32(HR_VIC_INT_EN_CLR, 0xFFFFFFFF);
}
/**
* @brief This function is used to register interrupt.
*
* @param[in] vec_no interrupt no
* @param[in] handler
* @param[in] *data
*
* @return None
*
* @note None
*/
void tls_irq_register_handler(u8 vec_no, intr_handler_func handler, void *data)
{
// ASSERT (vec_no >= 0 && vec_no <= 0x1f);
if (NULL == intr_handler_vect[vec_no])
{
intr_handler_vect[vec_no] = tls_mem_alloc(sizeof(tls_irq_handler_t));
}
if (intr_handler_vect[vec_no])
{
intr_handler_vect[vec_no]->handler = handler;
intr_handler_vect[vec_no]->data = data;
// intr_handler_vect[vec_no].name = NULL;
intr_handler_vect[vec_no]->counter = 0;
}
}
extern void NVIC_Configration(int irqno, FunctionalState irqstatus);
/**
* @brief This function is used to enable interrupt.
*
* @param[in] vec_no interrupt no
*
* @return None
*
* @note None
*/
void tls_irq_enable(u8 vec_no)
{
NVIC_ClearPendingIRQ((IRQn_Type)vec_no);
NVIC_Configration(vec_no, ENABLE);
}
/**
* @brief This function is used to disable interrupt.
*
* @param[in] vec_no interrupt no
*
* @return None
*
* @note None
*/
void tls_irq_disable(u8 vec_no)
{
NVIC_Configration(vec_no, DISABLE);
NVIC_ClearPendingIRQ((IRQn_Type)vec_no);
}
/**
* @brief This function is used to set interrupt priority.
*
* @param[in] vec_no interrupt no
* @param[in] priority priority
*
* @return None
*
* @note None
*/
void tls_irq_set_priority(u8 vec_no, u8 priority)
{
NVIC_SetPriority(vec_no, priority);
}
void OS_CPU_IRQ_ISR_Handler(void)
{
u32 irq_status = tls_reg_read32(HR_VIC_IRQ_STATUS);
int i = 0;
intr_counter++;
for (i = 0; i < INTR_CNT; i++)
{
if (irq_status & (1UL << i))
{
intr_handler_vect[i]->handler((void *) intr_handler_vect[i]->data);
intr_handler_vect[i]->counter++;
}
}
intr_counter--;
/* clear interrupt */
tls_reg_write32(HR_VIC_VECT_ADDR, 0);
}
+187
View File
@@ -0,0 +1,187 @@
/**************************************************************************//**
* @file wm_lcd.c
* @author
* @version
* @date
* @brief
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd. All rights reserved.
*****************************************************************************/
#include "wm_lcd.h"
#define RTC_CLK (32000UL)
/**
* @brief Initialize LCD Frame Counter
* @param[in] freq LCD reference refresh frequency in Hz that will be used
*/
void tls_lcd_fresh_ratio(uint16_t freq)
{
uint8_t com_num;
if (freq == 0)
{
freq = 60;
}
com_num = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos) ? 4 : 8;
LCD->FRAMECNT = RTC_CLK/(com_num * freq);
}
/**
* @brief
* Turn on or clear a segment
*
* @param[in] com
* Which COM line to update
*
* @param[in] bit
* Bit index of which field to change
*
* @param[in] enable
* When one will set segment, when zero will clear segment
*
* @param[in] mode
* when one max configuration is 4x20, when zero max configuration is 8x16
*
*/
void tls_lcd_seg_set(int com, int bit, int on_off)
{
int mode;
/** get the mode congfig when one max configuration is 4x20, when zero max configuration is 8x16 */
mode = tls_bitband_read(HR_LCD_CR, LCD_CR_MODE_Pos);
if (!mode && (com < 0 || com > 7) && (bit < 0 || bit > 15))
{
return ;
}
if (mode && (com < 0 || com > 3) && (bit < 0 || bit > 19))
{
return ;
}
switch(com)
{
/** COM0 */
case 0:
tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off);
break;
/** COM1 */
case 1:
if (mode)
tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off);
else
{
bit += 16;
tls_bitband_write(HR_LCD_COM0_1_SEG, bit, on_off);
}
break;
/** COM2 */
case 2:
if (mode)
tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off);
else
tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off);
break;
/** COM3 */
case 3:
if (mode)
tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off);
else
{
bit += 16;
tls_bitband_write(HR_LCD_COM2_3_SEG, bit, on_off);
}
break;
/** COM4 */
case 4:
tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off);
break;
/** COM5 */
case 5:
bit += 16;
tls_bitband_write(HR_LCD_COM4_5_SEG, bit, on_off);
break;
/** COM6 */
case 6:
tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off);
break;
/** COM7 */
case 7:
bit += 16;
tls_bitband_write(HR_LCD_COM6_7_SEG, bit, on_off);
break;
default:
break;
}
}
/**
* @brief enable or disable the LCD module gpio
*
* @param[in] the config value per bit for one of LCD gpios, set 1 gpio output enable ,0 output disabled
*
*/
void tls_lcd_io_config(unsigned int val)
{
tls_reg_write32(HR_LCD_IO_EN, val);
}
/**
* @brief
* select the voltage of LCD module
*
*/
void tls_lcd_vlcd_sel(LCD_VlcdDef vlcd)
{
LCD->CTRL &= ~LCD_VLCD_MASK;
LCD->CTRL |= vlcd;
}
/**
* @brief
* set the duty of LCD module
*
*/
void tls_lcd_duty_set(LCD_DutyDef duty)
{
LCD->CTRL &= ~LCD_DUTY_MASK;
LCD->CTRL |= duty;
}
/**
* @brief
* set the bias of LCD module
*
*/
void tls_lcd_bias_set(LCD_BiasDef bias)
{
LCD->CTRL &= ~LCD_BIAS_MASK;
LCD->CTRL |= bias;
}
/**
* @brief
* initialize the lcd module
*
*/
void tls_lcd_init(tls_lcd_options_t *opts)
{
LCD->CTRL = 0;
LCD->CTRL = opts->mode | opts->bias | opts->duty | opts->vlcd | (1 << 12);
tls_lcd_fresh_ratio(opts->fresh_rate);
TLS_LCD_ENABLE(opts->enable);
TLS_LCD_POWERDOWM(0);
}
+332
View File
@@ -0,0 +1,332 @@
#include <string.h>
#include "wm_debug.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_pwm.h"
#include "wm_gpio.h"
#include "wm_timer.h"
#include "wm_cpu.h"
#include "tls_common.h"
#include "wm_pmu.h"
#include "wm_wifi.h"
struct pmu_irq_context {
tls_pmu_irq_callback callback;
void *arg;
};
static struct pmu_irq_context pmu_timer1_context = {0};
static struct pmu_irq_context pmu_timer0_context = {0};
static struct pmu_irq_context pmu_gpio_wake_context = {0};
static struct pmu_irq_context pmu_sdio_wake_context = {0};
void PMU_TIMER1_IRQHandler(void)
{
if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(1)) /* timer1 interrupt */
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(1)); /* clear timer1 interrupt */
if (NULL != pmu_timer1_context.callback)
pmu_timer1_context.callback(pmu_timer1_context.arg);
}
return;
}
void PMU_TIMER0_IRQHandler(void)
{
if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(0)) /* timer0 interrupt */
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(0)); /* clear timer0 interrupt */
tls_reg_write32(HR_PMU_TIMER0, tls_reg_read32(HR_PMU_TIMER0) & (~BIT(16)));
if (NULL != pmu_timer0_context.callback)
pmu_timer0_context.callback(pmu_timer0_context.arg);
}
return;
}
void PMU_GPIO_WAKE_IRQHandler(void)
{
if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(2)) /* gpio wake interrupt */
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(2)); /* clear gpio wake interrupt */
if (NULL != pmu_gpio_wake_context.callback)
pmu_gpio_wake_context.callback(pmu_gpio_wake_context.arg);
}
return;
}
void PMU_SDIO_WAKE_IRQHandler(void)
{
if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(3)) /* sdio wake interrupt */
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, tls_reg_read32(HR_PMU_INTERRUPT_SRC) | BIT(3)); /* clear sdio wake interrupt */
if (NULL != pmu_sdio_wake_context.callback)
pmu_sdio_wake_context.callback(pmu_sdio_wake_context.arg);
}
return;
}
/**
* @brief This function is used to register pmu timer1 interrupt
*
* @param[in] callback the pmu timer1 interrupt call back function
* @param[in] arg parameter of call back function
*
* @return None
*
* @note
* user not need clear interrupt flag.
* pmu timer1 callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_pmu_timer1_isr_register(tls_pmu_irq_callback callback, void *arg)
{
pmu_timer1_context.callback = callback;
pmu_timer1_context.arg = arg;
tls_irq_enable(PMU_TIMER1_INT);
return;
}
/**
* @brief This function is used to register pmu timer0 interrupt
*
* @param[in] callback the pmu timer0 interrupt call back function
* @param[in] arg parameter of call back function
*
* @return None
*
* @note
* user not need clear interrupt flag.
* pmu timer0 callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_pmu_timer0_isr_register(tls_pmu_irq_callback callback, void *arg)
{
pmu_timer0_context.callback = callback;
pmu_timer0_context.arg = arg;
tls_irq_enable(PMU_TIMER0_INT);
return;
}
/**
* @brief This function is used to register pmu gpio interrupt
*
* @param[in] callback the pmu gpio interrupt call back function
* @param[in] arg parameter of call back function
*
* @return None
*
* @note
* user not need clear interrupt flag.
* pmu gpio callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_pmu_gpio_isr_register(tls_pmu_irq_callback callback, void *arg)
{
pmu_gpio_wake_context.callback = callback;
pmu_gpio_wake_context.arg = arg;
tls_irq_enable(PMU_GPIO_WAKEUP_INT);
return;
}
/**
* @brief This function is used to register pmu sdio interrupt
*
* @param[in] callback the pmu sdio interrupt call back function
* @param[in] arg parameter of call back function
*
* @return None
*
* @note
* user not need clear interrupt flag.
* pmu sdio callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_pmu_sdio_isr_register(tls_pmu_irq_callback callback, void *arg)
{
pmu_sdio_wake_context.callback = callback;
pmu_sdio_wake_context.arg = arg;
tls_irq_enable(PMU_SDIO_WAKEUP_INT);
return;
}
/**
* @brief This function is used to select pmu clk
*
* @param[in] bypass pmu clk whether or not use bypass mode
* ohter pmu clk use 32K by 40MHZ
* 0 pmu clk 32K by calibration circuit
*
* @return None
*
* @note None
*/
void tls_pmu_clk_select(u8 bypass)
{
u32 val;
val = tls_reg_read32(HR_PMU_PS_CR);
if(bypass)
{
val |= BIT(3);
}
else
{
val &= ~BIT(3);
}
val |= BIT(2);
tls_reg_write32(HR_PMU_PS_CR, val);
}
/**
* @brief This function is used to start pmu timer0
*
* @param[in] second vlaue of timer0 count[s]
*
* @return None
*
* @note None
*/
void tls_pmu_timer0_start(u16 second)
{
u32 val;
val = second;
val |= BIT(16);
tls_reg_write32(HR_PMU_TIMER0, val);
}
/**
* @brief This function is used to stop pmu timer0
*
* @param None
*
* @return None
*
* @note None
*/
void tls_pmu_timer0_stop(void)
{
u32 val;
val = tls_reg_read32(HR_PMU_TIMER0);
val &= ~BIT(16);
tls_reg_write32(HR_PMU_TIMER0, val);
}
/**
* @brief This function is used to start pmu timer1
*
* @param[in] second vlaue of timer1 count[ms]
*
* @return None
*
* @note None
*/
void tls_pmu_timer1_start(u16 msec)
{
u32 val;
//默认采用最小单位1ms
val = (msec-1) | (1<<16) | (1<<17) | (0<<20) | (0<<24);
tls_reg_write32(HR_PMU_TIMER1, val);
}
/**
* @brief This function is used to stop pmu timer1
*
* @param None
*
* @return None
*
* @note None
*/
void tls_pmu_timer1_stop(void)
{
u32 val;
val = tls_reg_read32(HR_PMU_TIMER1);
val &= ~BIT(16);
val &= ~BIT(17);
tls_reg_write32(HR_PMU_TIMER1, val);
}
/**
* @brief This function is used to start pmu goto standby
*
* @param None
*
* @return None
*
* @note None
*/
void tls_pmu_standby_start(void)
{
u32 val;
tls_irq_enable(PMU_GPIO_WAKEUP_INT); //默认打开中断为了清楚IO唤醒的中断标记
val = tls_reg_read32(HR_PMU_PS_CR);
TLS_DBGPRT_INFO("goto standby here\n");
val |= BIT(0);
tls_reg_write32(HR_PMU_PS_CR, val);
}
/**
* @brief This function is used to close peripheral's clock
*
* @param[in] devices peripherals
*
* @return None
*
* @note None
*/
void tls_close_peripheral_clock(tls_peripheral_type_s devices)
{
tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) & ~(devices));
return;
}
/**
* @brief This function is used to open peripheral's clock
*
* @param[in] devices peripherals
*
* @return None
*
* @note None
*/
void tls_open_peripheral_clock(tls_peripheral_type_s devices)
{
tls_reg_write32(HR_CLK_BASE_ADDR, tls_reg_read32(HR_CLK_BASE_ADDR) | devices);
return;
}
+919
View File
@@ -0,0 +1,919 @@
/**
* @file wm_pwm.c
*
* @brief pwm driver module
*
* @author dave
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include <string.h>
#include "wm_debug.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_pwm.h"
#include "wm_gpio.h"
#include "wm_cpu.h"
#include "tls_common.h"
typedef void (*pwm_irq_callback)(void);
static pwm_irq_callback pwm_callback;
void PWM_IRQHandler(void)
{
if (pwm_callback)
pwm_callback();
}
/**
* @brief This function is used to register the pwm interrupt callback function
*
* @param[in] callback the pwm interrupt callback function
*
* @return None
*
* @note None
*/
void tls_pwm_isr_register(void (*callback)(void))
{
pwm_callback = callback;
tls_irq_enable(PWM_INT);
}
/**
* @brief This function is used to set duty ratio
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] duty Number of active levels
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_duty_config(u8 channel, u8 duty)
{
u32 temp = 0;
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
{
TLS_DBGPRT_ERR("duty param err\n");
return WM_FAILED;
}
if (duty == 0)
{
tls_pwm_stop(channel);
return WM_SUCCESS;
}
if (4 == channel)
{
temp = tls_reg_read32(HR_PWM_CH4_REG2) & ~0x0000FF00;
temp |= (duty << 8);
tls_reg_write32(HR_PWM_CH4_REG2, temp); /* duty radio */
}
else
{
temp = tls_reg_read32(HR_PWM_CMPDAT) & ~(0xFF << channel * 8);
temp |= (duty << (channel * 8));
tls_reg_write32(HR_PWM_CMPDAT, temp); /* duty radio */
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set frequency
*
* @param[in] channel pwm channel NO., range form 0 to 4
* @param[in] clkdiv clock divider, range 0 to 65535
* @param[in] period the number of the counting clock cycle
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_freq_config(u8 channel, u16 clkdiv, u8 period)
{
u32 temp = 0;
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
{
TLS_DBGPRT_ERR("freq param err\n");
return WM_FAILED;
}
if (4 == channel)
{
temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0xFFFF0000;
temp |= (clkdiv << 16);
tls_reg_write32(HR_PWM_CH4_REG1, temp);/* clock divider */
temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x0000FF00;
temp |= (period << 8);
tls_reg_write32(HR_PWM_CH4_REG1, temp); /* the number of the counting clock cycle */
}
else
{
temp = tls_reg_read32(HR_PWM_CLKDIV01 + (channel / 2) * 4) & ~(0xFFFF << ((channel % 2) * 16));
temp |= (clkdiv << ((channel % 2) * 16));
tls_reg_write32(HR_PWM_CLKDIV01 + (channel / 2) * 4, temp);/* clock divider */
temp = tls_reg_read32(HR_PWM_PERIOD) & ~(0xFF << channel * 8);
temp |= (period << (channel * 8));
tls_reg_write32(HR_PWM_PERIOD, temp);/* the number of the counting clock cycle */
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set the output mode
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] mode pwm work mode for signal generate
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_out_mode_config(u8 channel, enum tls_pwm_out_mode mode)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (WM_PWM_OUT_MODE_BRAKE == mode)
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11 + channel));/* the brake mode */
else if (WM_PWM_OUT_MODE_ALLSYC == mode)
{
if (channel != 0)
return WM_FAILED;
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~0xF800); /* disable the brake mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(6)); /* enable the all synchronous mode mode */
}
else if (WM_PWM_OUT_MODE_2SYC == mode)
{
if (channel != 0 && channel != 2)
return WM_FAILED;
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800<<channel)); /* disable the brake mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(6)); /* disable the all synchronous mode mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(14 + channel / 2)); /* enable the two channel synchronous mode */
}
else if (WM_PWM_OUT_MODE_MC == mode)
{
if (channel != 0 && channel != 2)
return WM_FAILED;
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & ~(0x1800<<channel));/* disable the brake mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(6)); /* disable the all synchronous mode mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & ~BIT(14 + channel / 2)); /* disable the two channel synchronous mode */
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(0 + channel / 2)); /* enable the complementary mode */
}
else if(WM_PWM_OUT_MODE_INDPT == mode)
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(6)));
if (channel != 4 )
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(0 + channel / 2)));
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(14 + channel / 2)));
}
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11 + channel))); /* enable the independent mode */
}
else
return WM_FAILED;
return WM_SUCCESS;
}
/**
* @brief This function is used to set the counting mode
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] cnt_type counting mode
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_cnt_type_config(u8 channel, enum tls_pwm_cnt_type cnt_type)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (4 == channel)
{
if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type)
{
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4)));
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3)));
}
if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type)
{
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(4)));
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(3));
}
else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type)
{
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(4));
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(3)));
}
}
else
{
if (WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP == cnt_type && channel == 0)
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17)));
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16)));
}
if (WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT == cnt_type)
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(17 + channel * 2)));
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(16 + channel * 2));
}
else if (WM_PWM_CNT_TYPE_CENTER_ALIGN == cnt_type)
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(17 + channel * 2));
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(16 + channel * 2)));
}
else
return WM_FAILED;
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set whether to loop
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] loop_mode whether to loop
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_loop_mode_config(u8 channel, enum tls_pwm_loop_type loop_mode)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (4 == channel)
{
if (WM_PWM_LOOP_TYPE_LOOP == loop_mode)
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(1));
else
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(1)));
}
else
{
if (WM_PWM_LOOP_TYPE_LOOP == loop_mode)
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(8 + channel));
else
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(8 + channel)));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set whether to inverse the output
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] en ENABLE or DISABLE
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_out_inverse_cmd(u8 channel, bool en)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (4 == channel)
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) | BIT(0));
else
tls_reg_write32(HR_PWM_CH4_REG2, tls_reg_read32(HR_PWM_CH4_REG2) & (~BIT(0)));
}
else
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(2 + channel));
else
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(2 + channel)));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set the number of period to be generated
*
* @param[in] channel pwm channel NO.,range form 0 to 4
* @param[in] pnum the number of period to be generated,range from 0 to 255
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_stoptime_by_period_config(u8 channel, u8 pnum)
{
u32 temp = 0;
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (4 == channel)
{
temp = tls_reg_read32(HR_PWM_CH4_REG1) & ~0x000000FF;
temp |= pnum;
tls_reg_write32(HR_PWM_CH4_REG1, temp);
}
else
{
temp = tls_reg_read32(HR_PWM_PNUM) & ~(0xFF << channel * 8);
temp |= (pnum << (channel * 8));
tls_reg_write32(HR_PWM_PNUM, temp);
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set output enable
*
* @param[in] channel pwm channel NO.,channel 0 or channel 4
* @param[in] en ENABLE or DISABLE
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_output_en_cmd(u8 channel, bool en)
{
if(channel != 0 && channel != 4)
return WM_FAILED;
if (4 == channel)
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(2)));
else
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(2));
}
else
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(12)));
else
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(12));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set the dead time
*
* @param[in] channel pwm channel NO.,channel 0 or channel 2
* @param[in] dten whether enalbe the deat time, ENABLE or DISABLE
* @param[in] dtclkdiv dead zone clock divider, range 0 to 3
* @param[in] dtcnt the number of the counting clock cycle, range 0 to 255
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_deadzone_config(u8 channel, bool dten, u8 dtclkdiv, u8 dtcnt)
{
u32 temp = 0;
if ((channel !=0 && channel != 2) || dtclkdiv > 3)
return WM_FAILED;
if(ENABLE == dten)
{
temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x00030000;
temp |= (dtclkdiv<<16);
tls_reg_write32(HR_PWM_DTCTL, temp);/* dead zone clock divider */
if (channel == 0 || channel == 1)
{
temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x000000FF;
temp |= dtcnt;
tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */
tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(20)); /* whether enalbe the deat time */
}
else if (channel == 2 || channel == 3)
{
temp = tls_reg_read32(HR_PWM_DTCTL) & ~0x0000FF00;
temp |= (dtcnt<<8);
tls_reg_write32(HR_PWM_DTCTL, temp);/* the number of the counting clock cycle */
tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) | BIT(21)); /* whether enalbe the deat time */
}
}
else
{
if (channel == 0 || channel == 1)
{
tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(20))); /* whether enalbe the deat time */
}
else if (channel == 2 || channel == 3)
{
tls_reg_write32(HR_PWM_DTCTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(21))); /* whether enalbe the deat time */
}
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set whether to inverse the capture input
*
* @param[in] channel pwm channel NO.,channel 0 or channel 4
* @param[in] en ENABLE or DISABLE
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_capture_inverse_cmd(u8 channel, bool en)
{
if (channel != 0 && channel != 4)
return WM_FAILED;
if (channel == 0)
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(25));
else
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(25)));
}
else
{
if (ENABLE == en)
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(0));
else
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(0)));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set break mode
*
* @param[in] channel pwm channel NO.,channel 0 or channel 4
* @param[in] en whether enable the break mode,ENABLE or DISABLE
* @param[in] brok when break
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_brake_mode_config(u8 channel, bool en, enum tls_pwm_brake_out_level brok)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (ENABLE == en)
{
if (WM_PWM_BRAKE_OUT_HIGH == brok)
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(3+channel));
else
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(3+channel)));
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) | BIT(11+channel));
}
else
{
tls_reg_write32(HR_PWM_BRKCTL, tls_reg_read32(HR_PWM_BRKCTL) & (~BIT(11+channel)));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to enable the capture mode
*
* @param[in] channel pwm channel NO.,channel 0 or channel 4
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_capture_mode_config(u8 channel)
{
if (channel != 0 && channel != 4)
return WM_FAILED;
if (channel == 0)
{
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(24));
}
else
{
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(1));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set the interrupt about the number of period
*
* @param[in] channel pwm channel,range from 0 to 4
* @param[in] en enble or disable
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_stoptime_irq_cmd(u8 channel, bool en)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if (4 == channel)
{
if (en)
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(4));
else
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(4)));
}
else
{
if (en)
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(channel));
else
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(channel)));
}
return WM_SUCCESS;
}
/**
* @brief This function is used to set the interrupt about the
capture
*
* @param[in] channel pwm channel,channel 0 or channel 4
* @param[in] int_type interrupt type
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_capture_irq_type_config(u8 channel, enum tls_pwm_cap_int_type int_type)
{
if (channel != 0 && channel != 4)
return WM_FAILED;
if (0 == channel)
{
if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
}
else if (WM_PWM_CAP_RISING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(5));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6)));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
}
else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(6));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5)));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(7)));
}
else if(WM_PWM_CAP_DMA_INT == int_type)
{
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) | BIT(7));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(5)));
tls_reg_write32(HR_PWM_INTEN, tls_reg_read32(HR_PWM_INTEN) & (~BIT(6)));
}
}
else if (4 == channel)
{
if (WM_PWM_CAP_RISING_FALLING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
}
else if (WM_PWM_CAP_RISING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(8));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9)));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
}
else if (WM_PWM_CAP_FALLING_EDGE_INT == int_type)
{
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(9));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8)));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(10)));
}
else if(WM_PWM_CAP_DMA_INT == int_type)
{
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) | BIT(10));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(8)));
tls_reg_write32(HR_PWM_CAP2CTL, tls_reg_read32(HR_PWM_CAP2CTL) & (~BIT(9)));
}
}
return WM_SUCCESS;
}
/**
* @brief This function is used to initial pwm(out mode)
*
* @param[in] pwm_param structure containing the initialization parameters
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_out_init(pwm_init_param pwm_param)
{
int ret=0;
int pwm_status = 0;
if (pwm_param.channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
if(tls_reg_read32(HR_PWM_CTL) & BIT(27 + pwm_param.channel))
{
tls_pwm_stop(pwm_param.channel);
pwm_status = 1;
}
/* set output mode */
ret = tls_pwm_out_mode_config(pwm_param.channel, pwm_param.mode);
if (ret!=WM_SUCCESS)
return WM_FAILED;
if (WM_PWM_OUT_MODE_MC == pwm_param.mode)
{
/* set dead time */
ret = tls_pwm_deadzone_config(pwm_param.channel, pwm_param.dten, pwm_param.dtclkdiv, pwm_param.dtcnt);
if (ret!=WM_SUCCESS)
return WM_FAILED;
}
/* set count type */
tls_pwm_cnt_type_config(pwm_param.channel, pwm_param.cnt_type);
/* set period value and duty radio */
tls_pwm_freq_config(pwm_param.channel, pwm_param.clkdiv, pwm_param.period);
tls_pwm_duty_config(pwm_param.channel, pwm_param.duty);
/* set cycle type */
tls_pwm_loop_mode_config(pwm_param.channel, pwm_param.loop_type);
/* set output whether is inverse */
tls_pwm_out_inverse_cmd(pwm_param.channel, pwm_param.inverse_en);
/* set period number of generating */
tls_pwm_stoptime_by_period_config(pwm_param.channel, pwm_param.pnum);
/* set interrupt of period number whether is enable */
tls_pwm_stoptime_irq_cmd(pwm_param.channel, pwm_param.pnum_int);
/* set output status */
if (pwm_param.channel == 0 || pwm_param.channel == 4)
tls_pwm_output_en_cmd(pwm_param.channel, WM_PWM_OUT_EN_STATE_OUT);
if (pwm_param.mode == WM_PWM_OUT_MODE_ALLSYC && pwm_param.channel == 0)
tls_pwm_output_en_cmd(4, WM_PWM_OUT_EN_STATE_OUT);
if(pwm_status)
{
tls_pwm_start(pwm_param.channel);
}
return WM_SUCCESS;
}
/**
* @brief This function is used to initial pwm(capture mode)
*
* @param[in] channel pwm channel, channel 0 or channel 4
* @param[in] clkdiv clock divider, range 0 to 65535
* @param[in] inverse_en whether the input signal is reversed
* @param[in] int_type interrupt type
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_cap_init(u8 channel, u16 clkdiv, bool inverse_en, enum tls_pwm_cap_int_type int_type)
{
if (channel != 0 && channel != 4)
return WM_FAILED;
/* set clock divider and period value */
tls_pwm_freq_config(channel, clkdiv, 0xFF);
/* set input of capture mode whether is inverse */
tls_pwm_capture_inverse_cmd(channel, inverse_en);
/* set the capture mode */
tls_pwm_capture_mode_config(channel);
/* set count type (only edge alignment in the capture mode) */
tls_pwm_cnt_type_config(channel, WM_PWM_CNT_TYPE_EDGE_ALLGN_CAP);
/* set output status */
tls_pwm_output_en_cmd(channel, WM_PWM_OUT_EN_STATE_TRI);
/* set cycle mode (must be set int the capture mode) */
tls_pwm_loop_mode_config(channel, WM_PWM_LOOP_TYPE_LOOP);
/* set interrupt type */
tls_pwm_capture_irq_type_config(channel, int_type);
return WM_SUCCESS;
}
/**
* @brief This function is used to start pwm
*
* @param[in] channel pwm channel, range from 0 to 4
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_start(u8 channel)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) | BIT(27 + channel)); /* start counter */
return WM_SUCCESS;
}
/**
* @brief This function is used to stop pwm
*
* @param[in] channel pwm channel, range from 0 to 4
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_stop(u8 channel)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return WM_FAILED;
tls_reg_write32(HR_PWM_CTL, tls_reg_read32(HR_PWM_CTL) & (~BIT(27 + channel)));/* stop counter */
return WM_SUCCESS;
}
/**
* @brief This function is used to set pwm's frequency
*
* @param[in] channel pwm channel no, range form 0 to 4
* @param[in] freq frequency, range from 1 to 156250
*
* @return None
*
* @note None
*/
void tls_pwm_freq_set(u8 channel, u32 freq)
{
u16 clkdiv=0;
tls_sys_clk sysclk;
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return;
tls_sys_clk_get(&sysclk);
clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq;
tls_pwm_stop(channel);
tls_pwm_freq_config(channel, clkdiv, 255);
tls_pwm_start(channel);
}
/**
* @brief This function is used to set duty radio
*
* @param[in] channel pwm channel NO., range form 0 to 4
* @param[in] duty duty radio, range from 0 to 255
*
* @return None
*
* @note None
*/
void tls_pwm_duty_set(u8 channel, u8 duty)
{
if(channel > (PWM_CHANNEL_MAX_NUM - 1))
return;
tls_pwm_duty_config(channel, duty);
}
/**
* @brief This function is used to initial pwm
*
* @param[in] channel pwm channel, range from 0 to 4
* @param[in] freq freq range from 1 to 156250
* @param[in] duty duty range from 0 to 255
* @param[in] pnum period num,range from 0 to 255
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_init(u8 channel,u32 freq, u8 duty, u8 pnum)
{
pwm_init_param pwm_param;
int ret=-1;
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
memset(&pwm_param, 0, sizeof(pwm_init_param));
pwm_param.period = 255;
pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT;
pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP;
pwm_param.mode = WM_PWM_OUT_MODE_INDPT;
pwm_param.inverse_en = DISABLE;
pwm_param.pnum = pnum;
pwm_param.pnum_int = DISABLE;
pwm_param.duty = duty;
pwm_param.channel = channel;
pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq;
// printf("clkdiv:%d\n", pwm_param.clkdiv);
ret = tls_pwm_out_init(pwm_param);
// tls_pwm_start(channel);
return ret;
}
/**
* @brief This function is used to initial pwm
*
* @param[in] channel pwm channel, range from 0 to 4
* @param[in] freq freq range from 1 to 156250
* @param[in] duty duty range from 0 to 255
* @param[in] pnum period num,range from 0 to 255
*
* @retval WM_SUCCESS success
* @retval WM_FAILED failed
*
* @note None
*/
int tls_pwm_ineverse_init(u8 channel,u32 freq, u8 duty, u8 pnum)
{
pwm_init_param pwm_param;
int ret=-1;
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
memset(&pwm_param, 0, sizeof(pwm_init_param));
pwm_param.period = 255;
pwm_param.cnt_type = WM_PWM_CNT_TYPE_EDGE_ALIGN_OUT;
pwm_param.loop_type = WM_PWM_LOOP_TYPE_LOOP;
pwm_param.mode = WM_PWM_OUT_MODE_INDPT;
pwm_param.inverse_en = ENABLE;
pwm_param.pnum = pnum;
pwm_param.pnum_int = DISABLE;
pwm_param.duty = duty;
pwm_param.channel = channel;
pwm_param.clkdiv = sysclk.apbclk*UNIT_MHZ/256/freq;
// printf("clkdiv:%d\n", pwm_param.clkdiv);
ret = tls_pwm_out_init(pwm_param);
// tls_pwm_start(channel);
return ret;
}
+170
View File
@@ -0,0 +1,170 @@
/**
* @file wm_rtc.c
*
* @brief rtc Driver Module
*
* @author dave
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wm_regs.h"
#include "wm_rtc.h"
#include "wm_irq.h"
#include "tls_common.h"
struct rtc_irq_context {
tls_rtc_irq_callback callback;
void *arg;
};
static struct rtc_irq_context rtc_context = {0};
/**
* @brief This function is used to set pmu rtc time
*
* @param[in] tblock time value
*
* @return None
*
* @note None
*/
void tls_set_rtc(struct tm *tblock)
{
int ctrl1 = 0;
int ctrl2 = 0;
ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* disable */
ctrl2 &= ~(1 << 16);
tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
ctrl1 |= tblock->tm_sec;
ctrl1 |= tblock->tm_min << 8;
ctrl1 |= tblock->tm_hour << 16;
ctrl1 |= tblock->tm_mday << 24;
tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1);
ctrl2 = 0;
ctrl2 |= tblock->tm_mon;
ctrl2 |= tblock->tm_year << 8;
tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2); /* enable */
ctrl2 |= (1 << 16);
tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2);
}
/**
* @brief This function is used to get pmu rtc time
*
* @param[out] tblock time value
*
* @return None
*
* @note None
*/
void tls_get_rtc(struct tm *tblock)
{
int ctrl1 = 0;
int ctrl2 = 0;
ctrl1 = tls_reg_read32(HR_PMU_RTC_CTRL1);
ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);
tblock->tm_year = ((int)((int)ctrl2 & 0x00007f00) >> 8);
tblock->tm_mon = (ctrl2 & 0x0000000f);
tblock->tm_mday = (ctrl1 & 0x1f000000) >> 24;
tblock->tm_hour = (ctrl1 & 0x001f0000) >> 16;
tblock->tm_min = (ctrl1 & 0x00003f00) >> 8;
tblock->tm_sec = ctrl1 & 0x0000003f;
}
void PMU_RTC_IRQHandler(void)
{
if (tls_reg_read32(HR_PMU_INTERRUPT_SRC) & BIT(5)) /* rtc interrupt */
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, BIT(5)); /* clear rtc interrupt */
if (NULL != rtc_context.callback)
rtc_context.callback(rtc_context.arg);
}
return;
}
/**
* @brief This function is used to register pmu rtc interrupt
*
* @param[in] callback the rtc interrupt call back function
* @param[in] arg parameter of call back function
*
* @return None
*
* @note
* user not need clear interrupt flag.
* rtc callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
void tls_rtc_isr_register(tls_rtc_irq_callback callback, void *arg)
{
rtc_context.callback = callback;
rtc_context.arg = arg;
// tls_reg_write32(HR_PMU_INTERRUPT_MASK, tls_reg_read32(HR_PMU_INTERRUPT_MASK) & (~BIT(4)));
tls_irq_enable(PMU_RTC_INT);
return;
}
/**
* @brief This function is used to start pmu rtc timer
*
* @param[in] tblock timer value
*
* @return None
*
* @note None
*/
void tls_rtc_timer_start(struct tm *tblock)
{
int ctrl1 = 0;
int ctrl2 = 0;
tls_irq_enable(PMU_RTC_INT);
ctrl1 |= tblock->tm_sec;
ctrl1 |= tblock->tm_min << 8;
ctrl1 |= tblock->tm_hour << 16;
ctrl1 |= tblock->tm_mday << 24;
ctrl2 |= tblock->tm_mon;
ctrl2 |= tblock->tm_year << 8;
tls_reg_write32(HR_PMU_RTC_CTRL2, ctrl2 | BIT(16));
tls_reg_write32(HR_PMU_RTC_CTRL1, ctrl1 | BIT(31));/* must set the enable */
return;
}
/**
* @brief This function is used to stop pmu rtc timer
*
* @param None
*
* @return None
*
* @note This function also is used to clear rtc timer interrupt
*/
void tls_rtc_timer_stop(void)
{
tls_irq_disable(PMU_RTC_INT);
tls_reg_write32(HR_PMU_RTC_CTRL1, tls_reg_read32(HR_PMU_RTC_CTRL1) & (~BIT(31)));
return;
}
File diff suppressed because it is too large Load Diff
+303
View File
@@ -0,0 +1,303 @@
/*****************************************************************************
*
* File Name : wm_spi_hal.h
*
* Description: host spi Driver Module
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
* All rights reserved.
*
* Author : dave
*
* Date : 2014-6-6
*****************************************************************************/
#include "wm_regs.h"
#include "list.h"
#include "wm_hostspi.h"
#include "wm_cpu.h"
static __inline void spi_set_mode(u8 mode);
static __inline void spi_set_mode(u8 mode)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_SPICFG_REG);
switch (mode) {
case TLS_SPI_MODE_0:
reg_val &= ~(0x03U);
reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(0));
break;
case TLS_SPI_MODE_1:
reg_val &= ~(0x03U);
reg_val |= (SPI_SET_CPOL(0) | SPI_SET_CPHA(1));
break;
case TLS_SPI_MODE_2:
reg_val &= ~(0x03U);
reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(0));
break;
case TLS_SPI_MODE_3:
reg_val &= ~(0x03U);
reg_val |= (SPI_SET_CPOL(1) | SPI_SET_CPHA(1));
break;
default:
break;
}
tls_reg_write32(HR_SPI_SPICFG_REG, reg_val);
}
static __inline void spi_set_endian(u8 endian)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_SPICFG_REG);
if (endian == 0) {
reg_val &= ~(0x01U << 3);
reg_val |= SPI_LITTLE_ENDIAN;
} else if(endian == 1) {
reg_val &= ~(0x01U << 3);
reg_val |= SPI_BIG_ENDIAN;
}
tls_reg_write32(HR_SPI_SPICFG_REG, reg_val);
}
static __inline void spi_set_chipselect_mode(u8 cs_active)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
if (cs_active == 0) {
reg_val &= ~(0x01U << 2);
reg_val |= SPI_CS_LOW;
} else if(cs_active == 1) {
reg_val &= ~(0x01U << 2);
reg_val |= SPI_CS_HIGH;
}
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_clear_fifo(void)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
reg_val |= SPI_CLEAR_FIFOS;
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_set_rx_channel(u8 on_off)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
if (on_off == 0) {
reg_val &= ~(0x01U << 20);
reg_val |= SPI_RX_CHANNEL_OFF;
} else if(on_off == 1) {
reg_val &= ~(0x01U << 20);
reg_val |= SPI_RX_CHANNEL_ON;
}
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_set_tx_channel(u8 on_off)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
if (on_off == 0) {
reg_val &= ~(0x01U << 19);
reg_val |= SPI_TX_CHANNEL_OFF;
} else if(on_off == 1) {
reg_val &= ~(0x01U << 19);
reg_val |= SPI_TX_CHANNEL_ON;
}
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_set_sclk_length(u16 sclk_num, u8 invalid_rx_sclk_num)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
reg_val &= ~((0xffU << 23) | (0xffff << 3));
reg_val |= SPI_VALID_CLKS_NUM(sclk_num) | SPI_RX_INVALID_BITS(invalid_rx_sclk_num);
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_force_cs_out(u8 enable)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
if (enable) {
reg_val |= SPI_FORCE_SPI_CS_OUT;
} else {
reg_val &= ~SPI_FORCE_SPI_CS_OUT;
}
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_sclk_start(void)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_CHCFG_REG);
reg_val |= SPI_START;
tls_reg_write32(HR_SPI_CHCFG_REG, reg_val);
}
static __inline void spi_set_sclk(u32 fclk)
{
u32 reg_val;
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
reg_val = tls_reg_read32(HR_SPI_CLKCFG_REG);
reg_val &= ~(0xffffU);
reg_val |= sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1;
tls_reg_write32(HR_SPI_CLKCFG_REG, reg_val);
}
static __inline void spi_set_tx_trigger_level(u8 level)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_MODECFG_REG);
reg_val &= ~(0x07U << 2);
reg_val |= SPI_TX_TRIGGER_LEVEL(level);
tls_reg_write32(HR_SPI_MODECFG_REG, reg_val);
}
static __inline void spi_set_rx_trigger_level(u8 level)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_MODECFG_REG);
reg_val &= ~(0x07U << 6);
reg_val |= SPI_RX_TRIGGER_LEVEL(level);
tls_reg_write32(HR_SPI_MODECFG_REG, reg_val);
}
static __inline void spi_set_timeout(u32 timeout, u8 enable)
{
u32 reg_val;
reg_val = SPI_TIME_OUT(timeout);
reg_val |= enable ? SPI_TIMER_EN : 0;
tls_reg_write32(HR_SPI_TIMEOUT_REG, reg_val);
}
static __inline void spi_get_status(u8 *busy, u8 *rx_fifo_level, u8 *tx_fifo_level)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_STATUS_REG);
if (busy) {*busy = SPI_IS_BUSY(reg_val);}
if (rx_fifo_level) {*rx_fifo_level = SPI_GET_RX_FIFO_CNT(reg_val);}
if (tx_fifo_level) {*tx_fifo_level = 32 - SPI_GET_TX_FIFO_CNT(reg_val);}
}
static __inline u32 spi_int_mask(void)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG);
return reg_val & SPI_INT_MASK_ALL;
}
static __inline void spi_mask_int(u32 mask)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG);
reg_val |= mask & SPI_INT_MASK_ALL;
tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val);
}
static __inline void spi_unmask_int(u32 mask)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_INT_MASK_REG);
reg_val &= ~(mask & SPI_INT_MASK_ALL);
tls_reg_write32(HR_SPI_INT_MASK_REG, reg_val);
}
static __inline u32 spi_get_int_status(void)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG);
return reg_val;
}
static __inline uint8_t spi_i2s_get_busy_status(void)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_STATUS_REG);
return SPI_IS_BUSY(reg_val);
}
static __inline void spi_clear_int_status(u32 int_srcs)
{
u32 reg_val;
reg_val = tls_reg_read32(HR_SPI_INT_STATUS_REG);
reg_val &= ~(int_srcs & SPI_INT_CLEAR_ALL);
reg_val |= int_srcs & SPI_INT_CLEAR_ALL;
tls_reg_write32(HR_SPI_INT_STATUS_REG, reg_val);
}
static __inline void spi_data_put(u32 data)
{
tls_reg_write32(HR_SPI_TXDATA_REG, data);
}
static __inline u32 spi_data_get(void)
{
return tls_reg_read32(HR_SPI_RXDATA_REG);
}
+319
View File
@@ -0,0 +1,319 @@
/**
* @file wm_timer.c
*
* @brief Timer Driver Module
*
* @author dave
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include "wm_type_def.h"
#include "wm_timer.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_cpu.h"
#include "tls_common.h"
enum tls_timer_id{
TLS_TIMER_ID_0 = 0, // used by delay (sleep, msleep, usleep)
TLS_TIMER_ID_1,
TLS_TIMER_ID_2,
TLS_TIMER_ID_3,
TLS_TIMER_ID_4,
TLS_TIMER_ID_5,
TLS_TIMER_ID_MAX
};
#define TIM0_USED_BY_DELAY 0
#define WM_TIMER_IRQ_USE_LOOP 1
struct timer_irq_context {
tls_timer_irq_callback callback;
void *arg;
};
static struct timer_irq_context timer_context[TLS_TIMER_ID_MAX] = {{0,0}};
u8 wm_timer_bitmap = 0;
#if WM_TIMER_IRQ_USE_LOOP
static void timer_irq_callback(void *p)
{
u8 i;
u32 value;
value = tls_reg_read32(HR_TIMER0_5_CSR);
value &= ~(TLS_TIMER_INT_CLR(TLS_TIMER_ID_0));
for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++)
{
if (value & TLS_TIMER_INT_CLR(i))
{
if (NULL != timer_context[i].callback)
timer_context[i].callback(timer_context[i].arg);
}
}
tls_reg_write32(HR_TIMER0_5_CSR, value);
return;
}
#else /* WM_TIMER_IRQ_USE_LOOP */
static void timer_clear_irq(int timer_id)
{
u8 i;
u32 value;
value = tls_reg_read32(HR_TIMER0_5_CSR);
for (i = TLS_TIMER_ID_0; i < TLS_TIMER_ID_MAX; i++)
{
value &= ~(TLS_TIMER_INT_CLR(i));
}
tls_reg_write32(HR_TIMER0_5_CSR, value | TLS_TIMER_INT_CLR(timer_id));
}
static void timer_irq_callback(void *p)
{
u8 timer_id;
timer_id = (u8)(u32)p;
if (NULL != timer_context[timer_id].callback)
timer_context[timer_id].callback(timer_context[timer_id].arg);
timer_clear_irq(timer_id);
return;
}
#endif /* WM_TIMER_IRQ_USE_LOOP */
void TIM0_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_0);
}
void TIM1_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_1);
}
void TIM2_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_2);
}
void TIM3_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_3);
}
void TIM4_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_4);
}
void TIM5_IRQHandler(void)
{
timer_irq_callback((void *)TLS_TIMER_ID_5);
}
/**
* @brief This function is used to create the timer
*
* @param[in] cfg timer configuration
*
* @retval WM_TIMER_ID_INVALID failed
* @retval other timer id[0~5]
*
* @note
* user not need clear interrupt flag.
* timer callback function is called in interrupt,
* so can not operate the critical data in the callback fuuction,
* recommendation to send messages to other tasks to operate it.
*/
u8 tls_timer_create(struct tls_timer_cfg *cfg)
{
u8 i;
int timer_csr;
for (i = TLS_TIMER_ID_1; i < TLS_TIMER_ID_MAX; i++)
{
if (!(wm_timer_bitmap & BIT(i)))
break;
}
if (TLS_TIMER_ID_MAX == i)
return WM_TIMER_ID_INVALID;
wm_timer_bitmap |= BIT(i);
timer_context[i].callback = cfg->callback;
timer_context[i].arg = cfg->arg;
tls_sys_clk sysclk;
tls_sys_clk_get(&sysclk);
tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1);
timer_csr = tls_reg_read32(HR_TIMER0_5_CSR);
if (!cfg->is_repeat)
timer_csr |= TLS_TIMER_ONE_TIME(i);
else
timer_csr &= ~(TLS_TIMER_ONE_TIME(i));
if (TLS_TIMER_UNIT_MS == cfg->unit)
timer_csr |= TLS_TIMER_MS_UNIT(i);
else
timer_csr &= ~(TLS_TIMER_MS_UNIT(i));
tls_reg_write32(HR_TIMER0_5_CSR, timer_csr | TLS_TIMER_INT_CLR(i));
if(cfg->timeout){
tls_reg_write32(HR_TIMER0_PRD + 0x04 * i, cfg->timeout);
}
tls_irq_enable(TIMER0_INT + i);
return i;
}
/**
* @brief This function is used to start the timer
*
* @param[in] timer_id timer id[0~5]
*
* @return None
*
* @note None
*/
void tls_timer_start(u8 timer_id)
{
if (!(wm_timer_bitmap & BIT(timer_id)))
return;
tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_EN(timer_id)| TLS_TIMER_EN(timer_id));
return;
}
/**
* @brief This function is used to stop the timer
*
* @param[in] timer_id timer id[0~5]
*
* @return None
*
* @note None
*/
void tls_timer_stop(u8 timer_id)
{
if (!(wm_timer_bitmap & BIT(timer_id)))
return;
tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR)|TLS_TIMER_INT_CLR(timer_id));
tls_reg_write32(HR_TIMER0_5_CSR, tls_reg_read32(HR_TIMER0_5_CSR) &~ TLS_TIMER_EN(timer_id));
return;
}
/**
* @brief This function is used to change a timer wait time
*
* @param[in] timer_id timer id[0~5]
*
* @param[in] newtime new wait time
*
* @retval None
*
* @note If the timer does not start, this function will start the timer
*/
void tls_timer_change(u8 timer_id, u32 newtime)
{
if (!(wm_timer_bitmap & BIT(timer_id)))
return;
tls_timer_stop(timer_id);
if (newtime)
tls_reg_write32(HR_TIMER0_PRD + 0x04 * timer_id, newtime);
tls_timer_start(timer_id);
return;
}
/**
* @brief This function is used to delete the timer
*
* @param[in] timer_id timer id[0~5]
*
* @return None
*
* @note None
*/
void tls_timer_destroy(u8 timer_id)
{
if (!(wm_timer_bitmap & BIT(timer_id)))
return;
tls_timer_stop(timer_id);
timer_context[timer_id].callback = NULL;
timer_context[timer_id].arg = NULL;
wm_timer_bitmap &= ~BIT(timer_id);
return;
}
/**
* @brief This function is create a delay to elapse
*
* @param[in] timeout the value writed into TMR0_PRD
* @param[in] m_flag millisecond flag in TIMER0
*
* @return 0
*
* @note None
*/
int tls_delay_via_timer(unsigned int timeout, unsigned int m_flag)
{
int ret = 0;
tls_sys_clk sysclk;
int timer_csr = 0;
if (0 == timeout)
return ret;
/*
* no lock
*
*/
tls_irq_disable(TIMER0_INT + TIM0_USED_BY_DELAY);
tls_reg_write32(HR_TIMER0_PRD + 0x04 * TIM0_USED_BY_DELAY,
timeout);
tls_sys_clk_get(&sysclk);
tls_reg_write32(HR_TIMER_CFG, sysclk.apbclk-1);
timer_csr = tls_reg_read32(HR_TIMER0_5_CSR);
if (TIMER_MS_UNIT_FLAG == m_flag)
timer_csr |= TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY);
else if (TIMER_US_UNIT_FLAG == m_flag)
timer_csr &= ~(TLS_TIMER_MS_UNIT(TIM0_USED_BY_DELAY));
timer_csr |= TLS_TIMER_ONE_TIME(TIM0_USED_BY_DELAY);
timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY);
timer_csr |= (TLS_TIMER_INT_EN(TIM0_USED_BY_DELAY));
timer_csr |= TLS_TIMER_EN(TIM0_USED_BY_DELAY);
tls_reg_write32(HR_TIMER0_5_CSR, timer_csr);
while (!(tls_reg_read32(HR_TIMER0_5_CSR)
& (TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY))))
;
timer_csr |= TLS_TIMER_INT_CLR(TIM0_USED_BY_DELAY);
tls_reg_write32(HR_TIMER0_5_CSR, timer_csr);
tls_irq_enable(TIMER0_INT + TIM0_USED_BY_DELAY);
/*
* no unlock
*
*/
return ret;
}
File diff suppressed because it is too large Load Diff
+160
View File
@@ -0,0 +1,160 @@
/**
* @file wm_watchdog.c
*
* @brief watchdog Driver Module
*
* @author kevin
*
* Copyright (c) 2014 Winner Microelectronics Co., Ltd.
*/
#include "wm_debug.h"
#include "wm_regs.h"
#include "wm_irq.h"
#include "wm_cpu.h"
#include "wm_watchdog.h"
static u32 wdg_jumpclear_flag = 0; /*0:donot jump clear, 1: jump clear, 2:close wdg*/
// void WDG_IRQHandler(void)
// {
// printf("WDG IRQ\n"); while(1) {};
// }
/**
* @brief This function is used to clear watchdog irq in case watchdog reset
*
* @param None
*
* @return None
*
* @note None
*/
void tls_watchdog_clr(void)
{
if (0 == wdg_jumpclear_flag)
{
tls_reg_write32(HR_WDG_INT_CLR, 0x01);
}
}
/**
* @brief This function is used to init watchdog
*
* @param[in] usec microseconds
*
* @return None
*
* @note None
*/
void tls_watchdog_init(u32 usec)
{
// tls_sys_clk sysclk;
// u32 apbclkcoff = 0;
// tls_sys_clk_get(&sysclk);
tls_irq_enable(WATCHDOG_INT);
//apbclkcoff = 40/sysclk.apbclk;
tls_reg_write32(HR_WDG_LOAD_VALUE, 40 * usec); /* 40M dominant frequency: 40 * 10^6 * (usec / 10^6) */
tls_reg_write32(HR_WDG_CTRL, 0x3); /* enable irq & reset */
}
/**
* @brief This function is used to deinit watchdog
*
* @param[in] None
*
* @return None
*
* @note None
*/
void tls_watchdog_deinit(void)
{
tls_irq_disable(WATCHDOG_INT);
tls_reg_write32(HR_WDG_CTRL, 0);
tls_reg_write32(HR_WDG_INT_CLR, 0x01);
}
/**
* @brief This function is used to start calculating elapsed time.
*
* @param[in] None
*
* @return elapsed time, unit:millisecond
*
* @note None
*/
void tls_watchdog_start_cal_elapsed_time(void)
{
if (tls_reg_read32(HR_WDG_CTRL)&0x3)
{
wdg_jumpclear_flag = 1;
tls_reg_write32(HR_WDG_INT_CLR, 0x01);
}
else
{
wdg_jumpclear_flag = 2;
tls_watchdog_init(5*1000*1000);
}
}
/**
* @brief This function is used to stop calculating & return elapsed time.
*
* @param[in] none
*
* @return elapsed time, unit:millisecond
*
* @note None
*/
u32 tls_watchdog_stop_cal_elapsed_time(void)
{
#define RT_TIME_BASE (40)
u32 val = 0;
switch (wdg_jumpclear_flag)
{
case 1:
{
val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE;
wdg_jumpclear_flag = 0;
}
break;
case 2:
{
val = (tls_reg_read32(HR_WDG_LOAD_VALUE) - tls_reg_read32(HR_WDG_CUR_VALUE))/RT_TIME_BASE;
wdg_jumpclear_flag = 0;
tls_watchdog_deinit();
}
break;
default:
wdg_jumpclear_flag = 0;
break;
}
return val;
}
/**
* @brief This function is used to reset system
*
* @param None
*
* @return None
*
* @note None
*/
void tls_sys_reset(void)
{
tls_sys_clk_set(CPU_CLK_40M);
tls_os_set_critical();
tls_reg_write32(HR_WDG_LOCK, 0x1ACCE551);
tls_reg_write32(HR_WDG_LOAD_VALUE, 0x100);
tls_reg_write32(HR_WDG_CTRL, 0x3);
tls_reg_write32(HR_WDG_LOCK, 1);
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef WM_DRIVER
#define WM_DRIVER
#include "../Platform/Drivers/uart/wm_uart.c"
#include "../Platform/Drivers/timer/wm_timer.c"
#include "../Platform/Drivers/spi/wm_hostspi.c"
#include "../Platform/Drivers/rtc/wm_rtc.c"
#include "../Platform/Drivers/pwm/wm_pwm.c"
#include "../Platform/Drivers/irq/wm_irq.c"
#include "../Platform/Drivers/i2c/wm_i2c.c"
#include "../Platform/Drivers/hspi/wm_hspi.c"
#include "../Platform/Drivers/gpio/wm_gpio.c"
#include "../Platform/Drivers/efuse/wm_efuse.c"
#include "../Platform/Drivers/dma/wm_dma.c"
#include "../Platform/Drivers/cpu/wm_cpu.c"
#include "../Platform/Drivers/adc/wm_adc.c"
#include "../Platform/Drivers/io/wm_io.c"
#include "../Platform/Drivers/i2s/wm_i2s.c"
#include "../Platform/Drivers/lcd/wm_lcd.c"
#include "../Platform/Drivers/pmu/wm_pmu.c"
#include "../Platform/Drivers/7816/wm_7816.c"
#include "../Platform/Drivers/internalflash/wm_internal_fls.c"
#include "../Platform/Drivers/flash/wm_fls.c"
#include "../Platform/Drivers/flash/wm_fls_gd25qxx.c"
#include "../Platform/Drivers/watchdog/wm_watchdog.c"
#include "../Platform/Drivers/gpio/wm_gpio_afsel.c"
#endif //WM_DRIVER