| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- #include "FreeRTOS.h"
- #include "board.h"
- #include "chip.h"
- #define ADC_CTR 0x00
- #define ADC_CFG 0x04
- #define ADC_IMR 0x08
- #define ADC_STA 0x0C
- #define ADC_AUX0 0x14
- #define ADC_AUX1 0x18
- #define ADC_AUX2 0x1C
- #define ADC_AUX3 0x20
- #define ADC_AUX4 0x38
- #define ADC_AUX5 0x3c
- #define ADC_AUX6 0x40
- #define ADC_AUX7 0x44
- #define ADC_DBNCNT 0x2C
- #define ADC_DETINTER 0x30
- #define ADC_SCTR 0x34
- #define ADC_CLK_FREQ 10000
- #define ADC_DEBOUNCE_CNT 0x50
- typedef struct adc_private_data {
- eAdcID id;
- uint32_t base;
- uint32_t irq;
- uint32_t clk_id;
- adc_int_cb ch_cb[ADC_CH_MAX];
- void *ch_cb_priv[ADC_CH_MAX];
- } adc_pdata_t;
- static adc_pdata_t g_adc[ADC_ID_MAX] = {
- [0] = {
- .id = 0,
- .base = REGS_ADC_BASE,
- .irq = ADC_IRQn,
- .clk_id = CLK_ADC,
- },
- [1] = {
- .id = 1,
- .base = REGS_ADC1_BASE,
- .irq = ADC1_IRQn,
- .clk_id = CLK_ADC1,
- },
- [2] = {
- .id = 2,
- .base = REGS_ADC2_BASE,
- .irq = ADC2_IRQn,
- .clk_id = CLK_ADC2,
- }
- };
- static uint32_t adc_get_int_bitoff(eAdcChannel ch)
- {
- uint32_t bitoff = 0;
- switch (ch) {
- case ADC_CH_AUX0:
- bitoff = 0;
- break;
- case ADC_CH_AUX1:
- bitoff = 3;
- break;
- case ADC_CH_AUX2:
- bitoff = 6;
- break;
- case ADC_CH_AUX3:
- bitoff = 9;
- break;
- case ADC_CH_AUX4:
- bitoff = 16;
- break;
- case ADC_CH_AUX5:
- bitoff = 19;
- break;
- case ADC_CH_AUX6:
- bitoff = 22;
- break;
- case ADC_CH_AUX7:
- bitoff = 25;
- break;
- }
- return bitoff;
- }
- static void adc_clear_int_status(adc_pdata_t *adc, eAdcChannel ch, uint32_t int_flg)
- {
- uint32_t val, bitoff;
- bitoff = adc_get_int_bitoff(ch);
- val = readl(adc->base + ADC_STA);
- val &= ~((int_flg & ADC_INT_MASK) << bitoff);
- writel(val, adc->base + ADC_STA);
- }
- static uint32_t adc_get_int_status(adc_pdata_t *adc, eAdcChannel ch)
- {
- uint32_t bitoff = 0;
- bitoff = adc_get_int_bitoff(ch);
- return (readl(adc->base + ADC_STA) >> bitoff) & ADC_INT_MASK;
- }
- static uint32_t adc_get_value(adc_pdata_t *adc, eAdcChannel ch)
- {
- uint32_t regoff;
- switch (ch) {
- case ADC_CH_AUX0:
- regoff = ADC_AUX0;
- break;
- case ADC_CH_AUX1:
- regoff = ADC_AUX1;
- break;
- case ADC_CH_AUX2:
- regoff = ADC_AUX2;
- break;
- case ADC_CH_AUX3:
- regoff = ADC_AUX3;
- break;
- case ADC_CH_AUX4:
- regoff = ADC_AUX4;
- break;
- case ADC_CH_AUX5:
- regoff = ADC_AUX5;
- break;
- case ADC_CH_AUX6:
- regoff = ADC_AUX6;
- break;
- case ADC_CH_AUX7:
- regoff = ADC_AUX7;
- break;
- }
- return readl(adc->base + regoff);
- }
- /*
- * clk unit = 1/pclk
- */
- static void adc_set_debounce_cnt(adc_pdata_t *adc, uint32_t debounce_cnt)
- {
- writel(debounce_cnt & 0xffffff, adc->base + ADC_DBNCNT);
- }
- /*
- * clk unit = 1/adc_clk
- */
- static void adc_set_transform_interval(adc_pdata_t *adc, uint32_t interval)
- {
- writel(interval & 0xffff, adc->base + ADC_DETINTER);
- }
- static void adc_reset(adc_pdata_t *adc)
- {
- uint32_t val;
- val = readl(adc->base + ADC_CTR);
- val |= (1 << 0);
- writel(val, adc->base + ADC_CTR);
- }
- static void adc_set_deinter(adc_pdata_t *adc, uint32_t count)
- {
- int mincnt, clkid;
- switch (adc->id) {
- case ADC0:
- clkid = CLK_ADC;
- break;
- case ADC1:
- clkid = CLK_ADC1;
- break;
- case ADC2:
- clkid = CLK_ADC2;
- break;
- default:
- return;
- }
- mincnt = ADC_DEBOUNCE_CNT * ulClkGetRate(clkid) / 2 / ulClkGetRate(CLK_APB);
- adc_set_transform_interval(adc, configMAX(mincnt, count));
- }
- static void adc_set_deinter_ms(adc_pdata_t *adc, uint32_t ms)
- {
- uint32_t count;
- count = (ms * ADC_CLK_FREQ)/1000;
- count /= 5;
- if(count < 0xffff)
- adc_set_deinter(adc, count);
- }
- static void adc_int_handler(void *para)
- {
- adc_pdata_t *adc = (adc_pdata_t *)para;
- adc_int_cb cb;
- uint32_t channel;
- uint32_t status;
- uint32_t imr;
- uint32_t int_en;
- imr = readl(adc->base + ADC_IMR);
- for (channel = ADC_CH_AUX0; channel < ADC_CH_MAX; channel++) {
- int_en = ~((imr >> adc_get_int_bitoff((eAdcChannel)channel)) & ADC_INT_MASK);
- status = adc_get_int_status(adc, (eAdcChannel)channel);
- if (status) {
- cb = adc->ch_cb[channel];
- if (cb && (status & int_en)) {
- cb((uint32_t)adc->id, status & int_en, adc_get_value(adc, (eAdcChannel)channel), adc->ch_cb_priv[channel]);
- }
- adc_clear_int_status(adc, (eAdcChannel)channel, status);
- }
- }
- }
- int adc_int_threshold_sel(eAdcID adc_id, int high)
- {
- uint32_t bitoff;
- bitoff = adc_id - ADC0 + 11;
- if (high)
- vSysctlConfigure(SYS_ANA_CFG, bitoff, 1, 1);
- else
- vSysctlConfigure(SYS_ANA_CFG, bitoff, 1, 0);
- return 0;
- }
- int adc_interrupt_enable(eAdcID id, eAdcChannel ch, uint32_t int_flg, int enable)
- {
- adc_pdata_t *adc;
- uint32_t bitoff;
- uint32_t val;
- if (id >= ADC_ID_MAX) {
- printf("%s, Invalid id:%d\n", __func__, id);
- return -1;
- }
- adc = &g_adc[id];
- bitoff = adc_get_int_bitoff(ch);
- val = readl(adc->base + ADC_IMR);
- if (enable)
- val &= ~((int_flg & ADC_INT_MASK) << bitoff);
- else
- val |= ((int_flg & ADC_INT_MASK) << bitoff);
- writel(val, adc->base + ADC_IMR);
- return 0;
- }
- int adc_force_conv_enable(eAdcID id, eAdcChannel ch, int enable)
- {
- adc_pdata_t *adc;
- uint32_t bitoff;
- uint32_t val;
- if (id >= ADC_ID_MAX) {
- printf("%s, Invalid id:%d\n", __func__, id);
- return -1;
- }
- adc = &g_adc[id];
- val = readl(adc->base + ADC_CTR);
- if (ch < ADC_CH_AUX4)
- bitoff = ch - ADC_CH_AUX0 + 13;
- else
- bitoff = ch - ADC_CH_AUX4 + 28;
- if (enable)
- val |= (1 << bitoff);
- else
- val &= ~(1 << bitoff);
- writel(val, adc->base + ADC_CTR);
- return 0;
- }
- /*
- * enable = 1,ADC值大于阈值时,触发中断。
- * enable = 0,ADC值小于阈值时,触发中断。
- */
- int adc_det_high_valid_enable(eAdcID id, eAdcChannel ch, int enable)
- {
- adc_pdata_t *adc;
- uint32_t bitoff;
- uint32_t val;
- if (id >= ADC_ID_MAX) {
- printf("%s, Invalid id:%d\n", __func__, id);
- return -1;
- }
- adc = &g_adc[id];
- val = readl(adc->base + ADC_CTR);
- if (ch < ADC_CH_AUX4)
- bitoff = ch - ADC_CH_AUX0 + 8;
- else
- bitoff = ch - ADC_CH_AUX4 + 24;
- if (enable)
- val |= (1 << bitoff);
- else
- val &= ~(1 << bitoff);
- writel(val, adc->base + ADC_CTR);
- return 0;
- }
- uint32_t adc_get_chn_val_force(eAdcID id, eAdcChannel ch)
- {
- int i;
- uint32_t adc_v;
- configASSERT(ch >= ADC_CH_AUX0 && ch <= ADC_CH_AUX7);
- for (i = ADC_CH_AUX0; i <= ADC_CH_AUX7; i++) {
- if (ch == i) {
- adc_enable(id, (eAdcChannel)i, 1);
- adc_force_conv_enable(id, (eAdcChannel)i, 1);
- adc_clear_int_status(&g_adc[id], (eAdcChannel)i, ADC_INT_MASK);
- } else {
- adc_enable(id, (eAdcChannel)i, 0);
- adc_force_conv_enable(id, (eAdcChannel)i, 0);
- }
- }
- while(!(adc_get_int_status(&g_adc[id], ch) & ADC_VALUE_INT)) {
- vTaskDelay(1);
- }
- return adc_get_value(&g_adc[id], ch);
- }
- int adc_register_int_cb(eAdcID id, eAdcChannel ch, adc_int_cb cb, void *user_param)
- {
- adc_pdata_t *adc;
- if (id >= ADC_ID_MAX) {
- printf("%s, Invalid id:%d\n", __func__, id);
- return -1;
- }
- adc = &g_adc[id];
- adc->ch_cb[ch] = cb;
- adc->ch_cb_priv[ch] = user_param;
- return 0;
- }
- int adc_enable(eAdcID id, eAdcChannel ch, int enable)
- {
- adc_pdata_t *adc;
- uint32_t bitoff;
- uint32_t val;
- if (id >= ADC_ID_MAX) {
- printf("%s, Invalid id:%d\n", __func__, id);
- return -1;
- }
- adc = &g_adc[id];
- if (id < ADC2) {
- // ADC 管脚需要将其设置为gpio输入
- gpio_direction_input((id - ADC0) * ADC_CH_MAX + ch + 111);
- } else {
- // 注:ADC2的AUX0~7的gpio功能由mcu控制,请在mcu上将对应gpio设置为输入。
- vSysctlConfigure(SYS_PAD_PUDCTL14, ch - ADC_CH_AUX0 + 16, 1, 1);
- }
- val = readl(adc->base + ADC_CTR);
- if (ch < ADC_CH_AUX4)
- bitoff = ch - ADC_CH_AUX0 + 3;
- else
- bitoff = ch - ADC_CH_AUX4 + 20;
- if (enable) {
- val |= (1 << bitoff);
- } else {
- val &= ~(1 << bitoff);
- }
- writel(val, adc->base + ADC_CTR);
- return 0;
- }
- int adc_init(void)
- {
- adc_pdata_t *adc;
- eAdcChannel channel;
- int id;
- for (id = 0; id < ADC_ID_MAX; id++) {
- #ifndef ADC0_SUPPORT
- if (id == ADC0)
- continue;
- #endif
- #ifndef ADC1_SUPPORT
- if (id == ADC1)
- continue;
- #endif
- #ifndef ADC2_SUPPORT
- if (id == ADC2)
- continue;
- #endif
- adc = &g_adc[id];
- vClkSetRate(adc->clk_id, ADC_CLK_FREQ);
- adc_reset(adc);
- for (channel = 0; channel < ADC_CH_MAX; channel++) {
- adc->ch_cb[channel] = NULL;
- adc->ch_cb_priv[channel] = NULL;
- /* disable all adc channel */
- adc_enable(id, channel, 0);
- /* disable and clear irq */
- adc_interrupt_enable(id, channel, ADC_INT_MASK, 0);
- adc_clear_int_status(adc, channel, ADC_INT_MASK);
- }
- /* set debounce count */
- adc_set_debounce_cnt(adc, ADC_DEBOUNCE_CNT);
- adc_set_deinter_ms(adc, 100);
- request_irq(adc->irq, 0, adc_int_handler, (void *)adc);
- }
- return 0;
- }
|