port to chopstx

This commit is contained in:
NIIBE Yutaka
2013-06-20 16:19:49 +09:00
parent 7c01cae4a5
commit ee7d72743e
30 changed files with 1349 additions and 759 deletions

View File

@@ -1,7 +1,7 @@
/*
* adc_stm32f103.c - ADC driver for STM32F103
*
* Copyright (C) 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a True Random Number Generator
@@ -22,15 +22,17 @@
*
*/
#include "ch.h"
#include "hal.h"
#include <stdint.h>
#include <stdlib.h>
#include <chopstx.h>
#include "neug.h"
#include "stm32f103.h"
#include "adc.h"
#define NEUG_CRC32_COUNTS 4
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define STM32_ADC_ADC1_IRQ_PRIORITY 5
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21)
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)
@@ -82,6 +84,7 @@
#define NEUG_DMA_MODE_CRC32 \
( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \
| STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
| STM32_DMA_CR_MINC \
| STM32_DMA_CR_TCIE | STM32_DMA_CR_TEIE)
#define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF) \
@@ -108,8 +111,10 @@
*/
void adc_init (void)
{
chSysLock ();
rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST);
RCC->APB2RSTR = 0;
ADC1->CR1 = 0;
ADC1->CR2 = ADC_CR2_ADON;
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
@@ -129,21 +134,48 @@ void adc_init (void)
while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
;
ADC2->CR2 = 0;
rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
chSysUnlock ();
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
}
static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags);
extern uint8_t __process4_stack_base__, __process4_stack_size__;
const uint32_t __stackaddr_adc = (uint32_t)&__process4_stack_base__;
const size_t __stacksize_adc = (size_t)&__process4_stack_size__;
#define PRIO_ADC 3
static void adc_lld_serve_rx_interrupt (uint32_t flags);
#define INTR_REQ_DMA1_Channel1 11
static void *
adc_intr_thread (void *arg)
{
chopstx_intr_t interrupt;
(void)arg;
chopstx_claim_irq (&interrupt, INTR_REQ_DMA1_Channel1);
while (1)
{
uint32_t flags;
chopstx_intr_wait (&interrupt);
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
DMA1->IFCR = STM32_DMA_ISR_MASK; /* Clear interrupt of channel 1. */
adc_lld_serve_rx_interrupt (flags);
}
return NULL;
}
static chopstx_t adc_thd;
void adc_start (void)
{
dmaStreamAllocate (NEUG_DMA_CHANNEL, STM32_ADC_ADC1_IRQ_PRIORITY,
adc_lld_serve_rx_interrupt, NULL);
dmaStreamSetPeripheral (NEUG_DMA_CHANNEL, &ADC1->DR);
/* Use DMA channel 1. */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
DMA1->IFCR = 0xffffffff;
chSysLock ();
rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
| ADC_CR1_SCAN);
@@ -169,12 +201,14 @@ void adc_start (void)
ADC1->CR2 = 0;
#endif
chSysUnlock ();
adc_thd = chopstx_create (PRIO_ADC, __stackaddr_adc, __stacksize_adc,
adc_intr_thread, NULL);
}
static int adc_mode;
static uint32_t *adc_ptr;
static int adc_size;
static uint32_t adc_buf[64];
static void adc_start_conversion_internal (void)
{
@@ -202,17 +236,19 @@ void adc_start_conversion (int mode, uint32_t *p, int size)
if (mode == ADC_SAMPLE_MODE)
{
dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, p);
dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size / 4);
dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_SAMPLE);
dmaStreamEnable (NEUG_DMA_CHANNEL);
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)p; /* SetMemory0 */
DMA1_Channel1->CNDTR = (uint32_t)size / 4; /* counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE_SAMPLE; /*mode*/
DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */
}
else
{
dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
dmaStreamEnable (NEUG_DMA_CHANNEL);
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)adc_buf; /* SetMemory0 */
DMA1_Channel1->CNDTR = size; /* counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE_CRC32; /*mode*/
DMA1_Channel1->CCR |= DMA_CCR1_EN; /* Enable */
}
adc_start_conversion_internal ();
@@ -221,7 +257,8 @@ void adc_start_conversion (int mode, uint32_t *p, int size)
static void adc_stop_conversion (void)
{
dmaStreamDisable (NEUG_DMA_CHANNEL);
DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
ADC1->CR2 = 0;
ADC2->CR2 = 0;
@@ -239,15 +276,16 @@ void adc_stop (void)
ADC2->CR1 = 0;
ADC2->CR2 = 0;
dmaStreamRelease (NEUG_DMA_CHANNEL);
rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
chopstx_cancel (adc_thd);
chopstx_join (adc_thd, NULL);
}
static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
static void adc_lld_serve_rx_interrupt (uint32_t flags)
{
(void)arg;
if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */
{
/* Should never happened. If any, it's coding error. */
@@ -262,27 +300,23 @@ static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
if (adc_mode != ADC_SAMPLE_MODE)
{
adc_size -= 4;
*adc_ptr++ = CRC->DR;
int i;
if (adc_size > 0)
for (i = 0; i < adc_size;)
{
dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
dmaStreamEnable (NEUG_DMA_CHANNEL);
adc_start_conversion_internal ();
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
CRC->DR = adc_buf[i++];
*adc_ptr++ = CRC->DR;
}
}
if (adc_mode == ADC_SAMPLE_MODE || adc_size <= 0)
{
chSysLockFromIsr();
if (rng_thread)
chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
chSysUnlockFromIsr();
}
chopstx_mutex_lock (&adc_mtx);
adc_data_available++;
if (adc_waiting)
chopstx_cond_signal (&adc_cond);
chopstx_mutex_unlock (&adc_mtx);
}
}
}