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.
518 lines
12 KiB
C
518 lines
12 KiB
C
|
||
/*****************************************************************************
|
||
*
|
||
* 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;
|
||
}
|
||
|
||
|
||
|