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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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. ***/
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user