Fix line-endings on LPC17xx and LPC43xx files
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6745 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
4353bdce7e
commit
24389bfe09
File diff suppressed because it is too large
Load Diff
|
@ -1,294 +1,294 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx ADC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/adc_lld.c
|
||||
* @brief LPC17xx ADC subsystem low level driver source.
|
||||
* @note Values in samples buffer are from DR register.
|
||||
* To get ADC values make conversion (DR >> 6) & 0x03FF.
|
||||
* DMA only support one ADC channel.
|
||||
* @addtogroup ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_ADC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief ADC1 driver identifier.*/
|
||||
ADCDriver ADCD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc17xx_dma_lli_config_t lpc_adc_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*/
|
||||
static void adc_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) {
|
||||
(void) flags;
|
||||
|
||||
if ((flags & (1 << LPC17xx_ADC_DMA_CHANNEL)) != 0) {
|
||||
_adc_isr_error_code(adcp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else if (adcp->half_buffer == false) {
|
||||
_adc_isr_half_code(adcp);
|
||||
adcp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_adc_isr_full_code(adcp);
|
||||
adcp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief ADC interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector98) {
|
||||
uint32_t status;
|
||||
uint32_t n;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
status = LPC_ADC->STAT;
|
||||
|
||||
n = ADCD1.num;
|
||||
|
||||
/* Note, an overrun may occur only in burst mode, if one or more
|
||||
conversions was (were) lost. */
|
||||
if ((status & ADC0STAT_OVERRUN_MASK)) {
|
||||
if (ADCD1.grpp != NULL)
|
||||
_adc_isr_error_code(&ADCD1, ADC_ERR_OVERRUN);
|
||||
}
|
||||
else {
|
||||
|
||||
status = status & ADC0STAT_DONE_MASK;
|
||||
for (i = 0; i < ADC_MAX_CHANNELS; i++) {
|
||||
if (status & (0x01 << i)) {
|
||||
ADCD1.samples[n] = LPC_ADC->DR[i];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == (ADCD1.nsamples / 2)) {
|
||||
_adc_isr_half_code(&ADCD1);
|
||||
}
|
||||
|
||||
if (n == ADCD1.nsamples) {
|
||||
n = 0;
|
||||
_adc_isr_full_code(&ADCD1);
|
||||
}
|
||||
}
|
||||
ADCD1.num = n;
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level ADC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_init(void) {
|
||||
|
||||
/* Driver initialization.*/
|
||||
adcObjectInit(&ADCD1);
|
||||
ADCD1.adc = LPC_ADC;
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
nvicDisableVector(ADC_IRQn);
|
||||
#else
|
||||
nvicEnableVector(ADC_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_ADC_IRQ_PRIORITY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the ADC peripheral.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_start(ADCDriver *adcp) {
|
||||
|
||||
/* If in stopped state then enables the ADC. */
|
||||
if (adcp->state == ADC_STOP) {
|
||||
LPC_SC->PCONP |= (1UL << 12); /* Enable ADC power */
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelAllocate(LPC17xx_ADC_DMA_CHANNEL, \
|
||||
(lpc17xx_dmaisr_t)adc_serve_dma_interrupt, \
|
||||
(void *)adcp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the ADC peripheral.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_stop(ADCDriver *adcp) {
|
||||
|
||||
/* If in ready state then disables the ADC clock.*/
|
||||
if (adcp->state == ADC_READY) {
|
||||
adcp->adc->CR = 0; /* Clear PDN bit */
|
||||
LPC_SC->PCONP &= ~(1UL << 12); /* Disable ADC power */
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelRelease(LPC17xx_ADC_DMA_CHANNEL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts an ADC conversion.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_start_conversion(ADCDriver *adcp) {
|
||||
|
||||
uint32_t dummy;
|
||||
uint32_t cr;
|
||||
uint8_t i;
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
uint32_t dma_ch_config;
|
||||
uint8_t ch;
|
||||
#endif
|
||||
|
||||
cr = adcp->grpp->cr0;
|
||||
adcp->num = 0;
|
||||
adcp->nsamples = adcp->depth * adcp->grpp->num_channels;
|
||||
|
||||
for (i = 0; i < ADC_MAX_CHANNELS; i++) {
|
||||
dummy = adcp->adc->DR[i]; /* Clear all DONE and OVERRUN flags. */
|
||||
}
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
adcp->half_buffer = false;
|
||||
|
||||
ch = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (cr & (1UL << i)) {
|
||||
ch = i; /* Get number of first enabled channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_adc_lli[0].srcaddr = (uint32_t)&adcp->adc->DR[ch];
|
||||
lpc_adc_lli[0].dstaddr = (uint32_t)&adcp->samples[0];
|
||||
lpc_adc_lli[0].lli = (uint32_t) &lpc_adc_lli[1];
|
||||
lpc_adc_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(adcp->nsamples/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_NOINC |
|
||||
DMA_CTRL_DST_INC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_adc_lli[1].srcaddr = lpc_adc_lli[0].srcaddr;
|
||||
lpc_adc_lli[1].dstaddr = (uint32_t)&adcp->samples[adcp->nsamples/2];
|
||||
lpc_adc_lli[1].control = lpc_adc_lli[0].control;
|
||||
|
||||
if (adcp->grpp->circular == true) {
|
||||
lpc_adc_lli[1].lli = (uint32_t) &lpc_adc_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_adc_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_SRC_PERIPH(DMA_ADC) |
|
||||
DMA_CFG_TTYPE_P2M |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].lli);
|
||||
dmaChannelControl(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].control);
|
||||
dmaChannelConfig(LPC17xx_ADC_DMA_CHANNEL, dma_ch_config);
|
||||
#endif
|
||||
|
||||
/* ADC configuration and conversion start. */
|
||||
adcp->adc->INTEN = adcp->grpp->inten; /* Set ADC interrupt on selected channels */
|
||||
adcp->adc->CR = (cr & 0x0000FFFF) | ((LPC17xx_ADC_CLKDIV - 1) << 8) | AD0CR_PDN;
|
||||
adcp->adc->CR |= cr & 0xFFFF0000;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_stop_conversion(ADCDriver *adcp) {
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelDisable(LPC17xx_ADC_DMA_CHANNEL);
|
||||
#endif
|
||||
adcp->adc->CR &= ~(AD0CR_MODE_BURST | AD0CR_START_MASK); /* Disable ADC conversion. */
|
||||
adcp->adc->INTEN = 0; /* Mask ADC interrupts. */
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAL_USE_ADC */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx ADC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/adc_lld.c
|
||||
* @brief LPC17xx ADC subsystem low level driver source.
|
||||
* @note Values in samples buffer are from DR register.
|
||||
* To get ADC values make conversion (DR >> 6) & 0x03FF.
|
||||
* DMA only support one ADC channel.
|
||||
* @addtogroup ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_ADC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief ADC1 driver identifier.*/
|
||||
ADCDriver ADCD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc17xx_dma_lli_config_t lpc_adc_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*/
|
||||
static void adc_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) {
|
||||
(void) flags;
|
||||
|
||||
if ((flags & (1 << LPC17xx_ADC_DMA_CHANNEL)) != 0) {
|
||||
_adc_isr_error_code(adcp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else if (adcp->half_buffer == false) {
|
||||
_adc_isr_half_code(adcp);
|
||||
adcp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_adc_isr_full_code(adcp);
|
||||
adcp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief ADC interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector98) {
|
||||
uint32_t status;
|
||||
uint32_t n;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
status = LPC_ADC->STAT;
|
||||
|
||||
n = ADCD1.num;
|
||||
|
||||
/* Note, an overrun may occur only in burst mode, if one or more
|
||||
conversions was (were) lost. */
|
||||
if ((status & ADC0STAT_OVERRUN_MASK)) {
|
||||
if (ADCD1.grpp != NULL)
|
||||
_adc_isr_error_code(&ADCD1, ADC_ERR_OVERRUN);
|
||||
}
|
||||
else {
|
||||
|
||||
status = status & ADC0STAT_DONE_MASK;
|
||||
for (i = 0; i < ADC_MAX_CHANNELS; i++) {
|
||||
if (status & (0x01 << i)) {
|
||||
ADCD1.samples[n] = LPC_ADC->DR[i];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == (ADCD1.nsamples / 2)) {
|
||||
_adc_isr_half_code(&ADCD1);
|
||||
}
|
||||
|
||||
if (n == ADCD1.nsamples) {
|
||||
n = 0;
|
||||
_adc_isr_full_code(&ADCD1);
|
||||
}
|
||||
}
|
||||
ADCD1.num = n;
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level ADC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_init(void) {
|
||||
|
||||
/* Driver initialization.*/
|
||||
adcObjectInit(&ADCD1);
|
||||
ADCD1.adc = LPC_ADC;
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
nvicDisableVector(ADC_IRQn);
|
||||
#else
|
||||
nvicEnableVector(ADC_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_ADC_IRQ_PRIORITY));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the ADC peripheral.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_start(ADCDriver *adcp) {
|
||||
|
||||
/* If in stopped state then enables the ADC. */
|
||||
if (adcp->state == ADC_STOP) {
|
||||
LPC_SC->PCONP |= (1UL << 12); /* Enable ADC power */
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelAllocate(LPC17xx_ADC_DMA_CHANNEL, \
|
||||
(lpc17xx_dmaisr_t)adc_serve_dma_interrupt, \
|
||||
(void *)adcp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the ADC peripheral.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_stop(ADCDriver *adcp) {
|
||||
|
||||
/* If in ready state then disables the ADC clock.*/
|
||||
if (adcp->state == ADC_READY) {
|
||||
adcp->adc->CR = 0; /* Clear PDN bit */
|
||||
LPC_SC->PCONP &= ~(1UL << 12); /* Disable ADC power */
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelRelease(LPC17xx_ADC_DMA_CHANNEL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts an ADC conversion.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_start_conversion(ADCDriver *adcp) {
|
||||
|
||||
uint32_t dummy;
|
||||
uint32_t cr;
|
||||
uint8_t i;
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
uint32_t dma_ch_config;
|
||||
uint8_t ch;
|
||||
#endif
|
||||
|
||||
cr = adcp->grpp->cr0;
|
||||
adcp->num = 0;
|
||||
adcp->nsamples = adcp->depth * adcp->grpp->num_channels;
|
||||
|
||||
for (i = 0; i < ADC_MAX_CHANNELS; i++) {
|
||||
dummy = adcp->adc->DR[i]; /* Clear all DONE and OVERRUN flags. */
|
||||
}
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
adcp->half_buffer = false;
|
||||
|
||||
ch = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (cr & (1UL << i)) {
|
||||
ch = i; /* Get number of first enabled channel. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_adc_lli[0].srcaddr = (uint32_t)&adcp->adc->DR[ch];
|
||||
lpc_adc_lli[0].dstaddr = (uint32_t)&adcp->samples[0];
|
||||
lpc_adc_lli[0].lli = (uint32_t) &lpc_adc_lli[1];
|
||||
lpc_adc_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(adcp->nsamples/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_NOINC |
|
||||
DMA_CTRL_DST_INC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_adc_lli[1].srcaddr = lpc_adc_lli[0].srcaddr;
|
||||
lpc_adc_lli[1].dstaddr = (uint32_t)&adcp->samples[adcp->nsamples/2];
|
||||
lpc_adc_lli[1].control = lpc_adc_lli[0].control;
|
||||
|
||||
if (adcp->grpp->circular == true) {
|
||||
lpc_adc_lli[1].lli = (uint32_t) &lpc_adc_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_adc_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_SRC_PERIPH(DMA_ADC) |
|
||||
DMA_CFG_TTYPE_P2M |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].lli);
|
||||
dmaChannelControl(LPC17xx_ADC_DMA_CHANNEL, lpc_adc_lli[0].control);
|
||||
dmaChannelConfig(LPC17xx_ADC_DMA_CHANNEL, dma_ch_config);
|
||||
#endif
|
||||
|
||||
/* ADC configuration and conversion start. */
|
||||
adcp->adc->INTEN = adcp->grpp->inten; /* Set ADC interrupt on selected channels */
|
||||
adcp->adc->CR = (cr & 0x0000FFFF) | ((LPC17xx_ADC_CLKDIV - 1) << 8) | AD0CR_PDN;
|
||||
adcp->adc->CR |= cr & 0xFFFF0000;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops an ongoing conversion.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void adc_lld_stop_conversion(ADCDriver *adcp) {
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
dmaChannelDisable(LPC17xx_ADC_DMA_CHANNEL);
|
||||
#endif
|
||||
adcp->adc->CR &= ~(AD0CR_MODE_BURST | AD0CR_START_MASK); /* Disable ADC conversion. */
|
||||
adcp->adc->INTEN = 0; /* Mask ADC interrupts. */
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAL_USE_ADC */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,347 +1,347 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx ADC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/adc_lld.h
|
||||
* @brief LPC17xx ADC subsystem low level driver header.
|
||||
* @note Values in samples buffer are from DR register.
|
||||
* To get ADC values make conversion (DR >> 6) & 0x03FF.
|
||||
* DMA only support one ADC channel.
|
||||
* @addtogroup ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _ADC_LLD_H_
|
||||
#define _ADC_LLD_H_
|
||||
|
||||
#if HAL_USE_ADC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define ADC0STAT_DONE_MASK 0x000000FF
|
||||
#define ADC0STAT_OVERRUN_MASK 0x0000FF00
|
||||
|
||||
#define AD0CR_PDN (1UL << 21)
|
||||
/**
|
||||
* @name Absolute Maximum Ratings
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Maximum ADC clock frequency.
|
||||
*/
|
||||
#define LPC17xx_ADCCLK_MAX 13000000
|
||||
|
||||
/**
|
||||
* @brief Available number of ADC channels.
|
||||
*/
|
||||
#define ADC_MAX_CHANNELS 8
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC settings
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Available analog channels
|
||||
* @note In software-controlled mode only
|
||||
* one channel can be selected.
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_CHANNEL0 (1UL << 0)
|
||||
#define AD0CR_CHANNEL1 (1UL << 1)
|
||||
#define AD0CR_CHANNEL2 (1UL << 2)
|
||||
#define AD0CR_CHANNEL3 (1UL << 3)
|
||||
#define AD0CR_CHANNEL4 (1UL << 4)
|
||||
#define AD0CR_CHANNEL5 (1UL << 5)
|
||||
#define AD0CR_CHANNEL6 (1UL << 6)
|
||||
#define AD0CR_CHANNEL7 (1UL << 7)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC mode types
|
||||
* @note In software-controlled mode only one conversion
|
||||
* is make
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_MODE_SOFT (0UL << 16)
|
||||
#define AD0CR_MODE_BURST (1UL << 16)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Triggers selection
|
||||
* @note Only use in software-controlled mode
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_START_NO (0UL << 24)
|
||||
#define AD0CR_START_NOW (1UL << 24)
|
||||
#define AD0CR_START_CT16B0_CAP0 (2UL << 24)
|
||||
#define AD0CR_START_CT32B0_CAP0 (3UL << 24)
|
||||
#define AD0CR_START_CT32B0_MAT0 (4UL << 24)
|
||||
#define AD0CR_START_CT32B0_MAT1 (5UL << 24)
|
||||
#define AD0CR_START_CT16B0_MAT0 (6UL << 24)
|
||||
#define AD0CR_START_CT16B0_MAT1 (7UL << 24)
|
||||
#define AD0CR_START_MASK (7UL << 24)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Trigger edge type selection
|
||||
* @note Only use in software-controlled mode.
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_EDGE_RISSING (0UL << 27)
|
||||
#define AD0CR_EDGE_FALLING (1UL << 27)
|
||||
/** @} */
|
||||
/** @} */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief ADC common clock divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_CLKDIV 12
|
||||
#endif
|
||||
|
||||
#if LPC17xx_PCLK/LPC17xx_ADC_CLKDIV > LPC17xx_ADCCLK_MAX
|
||||
#error "ADC clock frequency out of the acceptable range (13MHz max)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC DMA enable switch.
|
||||
* @details If set to @p TRUE the support for ADC DMA is included.
|
||||
* @note ADC DMA only support one selected channel. The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_USE_DMA) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_USE_DMA FALSE
|
||||
#endif
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA || defined(__DOXYGEN__)
|
||||
#if !defined(LPC17xx_DMA_REQUIRED)
|
||||
#define LPC17xx_DMA_REQUIRED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC DMA channel.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_DMA_CHANNEL DMA_CHANNEL6
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief ADC sample data type.
|
||||
*/
|
||||
typedef uint32_t adcsample_t;
|
||||
|
||||
/**
|
||||
* @brief Channels number in a conversion group.
|
||||
*/
|
||||
typedef uint16_t adc_channels_num_t;
|
||||
|
||||
/**
|
||||
* @brief Possible ADC failure causes.
|
||||
* @note Error codes are architecture dependent and should not relied
|
||||
* upon.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_ERR_OVERRUN = 1 /**< ADC overrun condition. */
|
||||
} adcerror_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an ADC driver.
|
||||
*/
|
||||
typedef struct ADCDriver ADCDriver;
|
||||
|
||||
/**
|
||||
* @brief ADC notification callback type.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object triggering the
|
||||
* callback
|
||||
* @param[in] buffer pointer to the most recent samples data
|
||||
* @param[in] n number of buffer rows available starting from @p buffer
|
||||
*/
|
||||
typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n);
|
||||
|
||||
/**
|
||||
* @brief ADC error callback type.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object triggering the
|
||||
* callback
|
||||
* @param[in] err ADC error code
|
||||
*/
|
||||
typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
|
||||
|
||||
/**
|
||||
* @brief Conversion group configuration structure.
|
||||
* @details This implementation-dependent structure describes a conversion
|
||||
* operation.
|
||||
* @note The use of this configuration structure requires knowledge of
|
||||
* LPC17xx ADC cell registers interface, please refer to the LPC17xx
|
||||
* reference manual for details.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Enables the circular buffer mode for the group.
|
||||
*/
|
||||
bool_t circular;
|
||||
/**
|
||||
* @brief Number of the analog channels belonging to the conversion group.
|
||||
*/
|
||||
adc_channels_num_t num_channels;
|
||||
/**
|
||||
* @brief Callback function associated to the group or @p NULL.
|
||||
*/
|
||||
adccallback_t end_cb;
|
||||
/**
|
||||
* @brief Error callback or @p NULL.
|
||||
*/
|
||||
adcerrorcallback_t error_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief ADC CR0 register initialization data.
|
||||
* @note All the required bits must be defined into this field.
|
||||
*/
|
||||
uint32_t cr0;
|
||||
/**
|
||||
* @brief ADC INTENT register initialization data.
|
||||
* @note In interrupt burst mode only define interrupt for
|
||||
* last enabled channel.
|
||||
*/
|
||||
uint32_t inten;
|
||||
} ADCConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t dummy;
|
||||
} ADCConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an ADC driver.
|
||||
*/
|
||||
struct ADCDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
adcstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const ADCConfig *config;
|
||||
/**
|
||||
* @brief Current samples buffer pointer or @p NULL.
|
||||
*/
|
||||
adcsample_t *samples;
|
||||
/**
|
||||
* @brief Current samples buffer depth or @p 0.
|
||||
*/
|
||||
size_t depth;
|
||||
/**
|
||||
* @brief Current conversion group pointer or @p NULL.
|
||||
*/
|
||||
const ADCConversionGroup *grpp;
|
||||
#if ADC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif
|
||||
#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the peripheral.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* ADC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(ADC_DRIVER_EXT_FIELDS)
|
||||
ADC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the ADCx registers block.
|
||||
*/
|
||||
LPC_ADC_TypeDef *adc;
|
||||
/**
|
||||
* @brief Number of all samples in buffer.
|
||||
*/
|
||||
uint32_t nsamples;
|
||||
/**
|
||||
* @brief Samples buffer counter.
|
||||
*/
|
||||
uint32_t num;
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern ADCDriver ADCD1;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void adc_lld_init(void);
|
||||
void adc_lld_start(ADCDriver *adcp);
|
||||
void adc_lld_stop(ADCDriver *adcp);
|
||||
void adc_lld_start_conversion(ADCDriver *adcp);
|
||||
void adc_lld_stop_conversion(ADCDriver *adcp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_ADC */
|
||||
|
||||
#endif /* _ADC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx ADC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/adc_lld.h
|
||||
* @brief LPC17xx ADC subsystem low level driver header.
|
||||
* @note Values in samples buffer are from DR register.
|
||||
* To get ADC values make conversion (DR >> 6) & 0x03FF.
|
||||
* DMA only support one ADC channel.
|
||||
* @addtogroup ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _ADC_LLD_H_
|
||||
#define _ADC_LLD_H_
|
||||
|
||||
#if HAL_USE_ADC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define ADC0STAT_DONE_MASK 0x000000FF
|
||||
#define ADC0STAT_OVERRUN_MASK 0x0000FF00
|
||||
|
||||
#define AD0CR_PDN (1UL << 21)
|
||||
/**
|
||||
* @name Absolute Maximum Ratings
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Maximum ADC clock frequency.
|
||||
*/
|
||||
#define LPC17xx_ADCCLK_MAX 13000000
|
||||
|
||||
/**
|
||||
* @brief Available number of ADC channels.
|
||||
*/
|
||||
#define ADC_MAX_CHANNELS 8
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC settings
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name Available analog channels
|
||||
* @note In software-controlled mode only
|
||||
* one channel can be selected.
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_CHANNEL0 (1UL << 0)
|
||||
#define AD0CR_CHANNEL1 (1UL << 1)
|
||||
#define AD0CR_CHANNEL2 (1UL << 2)
|
||||
#define AD0CR_CHANNEL3 (1UL << 3)
|
||||
#define AD0CR_CHANNEL4 (1UL << 4)
|
||||
#define AD0CR_CHANNEL5 (1UL << 5)
|
||||
#define AD0CR_CHANNEL6 (1UL << 6)
|
||||
#define AD0CR_CHANNEL7 (1UL << 7)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC mode types
|
||||
* @note In software-controlled mode only one conversion
|
||||
* is make
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_MODE_SOFT (0UL << 16)
|
||||
#define AD0CR_MODE_BURST (1UL << 16)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Triggers selection
|
||||
* @note Only use in software-controlled mode
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_START_NO (0UL << 24)
|
||||
#define AD0CR_START_NOW (1UL << 24)
|
||||
#define AD0CR_START_CT16B0_CAP0 (2UL << 24)
|
||||
#define AD0CR_START_CT32B0_CAP0 (3UL << 24)
|
||||
#define AD0CR_START_CT32B0_MAT0 (4UL << 24)
|
||||
#define AD0CR_START_CT32B0_MAT1 (5UL << 24)
|
||||
#define AD0CR_START_CT16B0_MAT0 (6UL << 24)
|
||||
#define AD0CR_START_CT16B0_MAT1 (7UL << 24)
|
||||
#define AD0CR_START_MASK (7UL << 24)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Trigger edge type selection
|
||||
* @note Only use in software-controlled mode.
|
||||
* @{
|
||||
*/
|
||||
#define AD0CR_EDGE_RISSING (0UL << 27)
|
||||
#define AD0CR_EDGE_FALLING (1UL << 27)
|
||||
/** @} */
|
||||
/** @} */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief ADC common clock divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_CLKDIV 12
|
||||
#endif
|
||||
|
||||
#if LPC17xx_PCLK/LPC17xx_ADC_CLKDIV > LPC17xx_ADCCLK_MAX
|
||||
#error "ADC clock frequency out of the acceptable range (13MHz max)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC DMA enable switch.
|
||||
* @details If set to @p TRUE the support for ADC DMA is included.
|
||||
* @note ADC DMA only support one selected channel. The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_USE_DMA) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_USE_DMA FALSE
|
||||
#endif
|
||||
|
||||
#if LPC17xx_ADC_USE_DMA || defined(__DOXYGEN__)
|
||||
#if !defined(LPC17xx_DMA_REQUIRED)
|
||||
#define LPC17xx_DMA_REQUIRED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC DMA channel.
|
||||
*/
|
||||
#if !defined(LPC17xx_ADC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_ADC_DMA_CHANNEL DMA_CHANNEL6
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief ADC sample data type.
|
||||
*/
|
||||
typedef uint32_t adcsample_t;
|
||||
|
||||
/**
|
||||
* @brief Channels number in a conversion group.
|
||||
*/
|
||||
typedef uint16_t adc_channels_num_t;
|
||||
|
||||
/**
|
||||
* @brief Possible ADC failure causes.
|
||||
* @note Error codes are architecture dependent and should not relied
|
||||
* upon.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_ERR_OVERRUN = 1 /**< ADC overrun condition. */
|
||||
} adcerror_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an ADC driver.
|
||||
*/
|
||||
typedef struct ADCDriver ADCDriver;
|
||||
|
||||
/**
|
||||
* @brief ADC notification callback type.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object triggering the
|
||||
* callback
|
||||
* @param[in] buffer pointer to the most recent samples data
|
||||
* @param[in] n number of buffer rows available starting from @p buffer
|
||||
*/
|
||||
typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n);
|
||||
|
||||
/**
|
||||
* @brief ADC error callback type.
|
||||
*
|
||||
* @param[in] adcp pointer to the @p ADCDriver object triggering the
|
||||
* callback
|
||||
* @param[in] err ADC error code
|
||||
*/
|
||||
typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
|
||||
|
||||
/**
|
||||
* @brief Conversion group configuration structure.
|
||||
* @details This implementation-dependent structure describes a conversion
|
||||
* operation.
|
||||
* @note The use of this configuration structure requires knowledge of
|
||||
* LPC17xx ADC cell registers interface, please refer to the LPC17xx
|
||||
* reference manual for details.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Enables the circular buffer mode for the group.
|
||||
*/
|
||||
bool_t circular;
|
||||
/**
|
||||
* @brief Number of the analog channels belonging to the conversion group.
|
||||
*/
|
||||
adc_channels_num_t num_channels;
|
||||
/**
|
||||
* @brief Callback function associated to the group or @p NULL.
|
||||
*/
|
||||
adccallback_t end_cb;
|
||||
/**
|
||||
* @brief Error callback or @p NULL.
|
||||
*/
|
||||
adcerrorcallback_t error_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief ADC CR0 register initialization data.
|
||||
* @note All the required bits must be defined into this field.
|
||||
*/
|
||||
uint32_t cr0;
|
||||
/**
|
||||
* @brief ADC INTENT register initialization data.
|
||||
* @note In interrupt burst mode only define interrupt for
|
||||
* last enabled channel.
|
||||
*/
|
||||
uint32_t inten;
|
||||
} ADCConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t dummy;
|
||||
} ADCConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an ADC driver.
|
||||
*/
|
||||
struct ADCDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
adcstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const ADCConfig *config;
|
||||
/**
|
||||
* @brief Current samples buffer pointer or @p NULL.
|
||||
*/
|
||||
adcsample_t *samples;
|
||||
/**
|
||||
* @brief Current samples buffer depth or @p 0.
|
||||
*/
|
||||
size_t depth;
|
||||
/**
|
||||
* @brief Current conversion group pointer or @p NULL.
|
||||
*/
|
||||
const ADCConversionGroup *grpp;
|
||||
#if ADC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif
|
||||
#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the peripheral.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* ADC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(ADC_DRIVER_EXT_FIELDS)
|
||||
ADC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the ADCx registers block.
|
||||
*/
|
||||
LPC_ADC_TypeDef *adc;
|
||||
/**
|
||||
* @brief Number of all samples in buffer.
|
||||
*/
|
||||
uint32_t nsamples;
|
||||
/**
|
||||
* @brief Samples buffer counter.
|
||||
*/
|
||||
uint32_t num;
|
||||
#if LPC17xx_ADC_USE_DMA
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern ADCDriver ADCD1;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void adc_lld_init(void);
|
||||
void adc_lld_start(ADCDriver *adcp);
|
||||
void adc_lld_stop(ADCDriver *adcp);
|
||||
void adc_lld_start_conversion(ADCDriver *adcp);
|
||||
void adc_lld_stop_conversion(ADCDriver *adcp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_ADC */
|
||||
|
||||
#endif /* _ADC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,210 +1,210 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/dac_lld.c
|
||||
* @brief LPC17xx DAC subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief CHN1 driver identifier.*/
|
||||
DACDriver DACD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc17xx_dma_lli_config_t lpc_dac_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief DAC DMA interrupt function.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] flags dma error flags
|
||||
*/
|
||||
static void dac_serve_dma_interrupt(DACDriver *dacp, uint32_t flags) {
|
||||
|
||||
if ((flags & (1 << LPC17xx_DAC_DMA_CHANNEL)) != 0) {
|
||||
_dac_isr_error_code(dacp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else {
|
||||
if (dacp->half_buffer == false) {
|
||||
_dac_isr_half_code(dacp);
|
||||
dacp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_dac_isr_full_code(dacp);
|
||||
dacp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level DAC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_init(void) {
|
||||
dacObjectInit(&DACD1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start(DACDriver *dacp) {
|
||||
|
||||
if (dacp->state == DAC_STOP) {
|
||||
|
||||
/* Enable DAC */
|
||||
LPC_PINCON->PINSEL1 |= (2UL << 20); /* Set AOUT P0.26 pin.*/
|
||||
|
||||
LPC_DAC->CR = 0;
|
||||
LPC_DAC->CTRL = 0;
|
||||
LPC_DAC->CNTVAL = LPC17xx_PCLK/dacp->config->frequency;
|
||||
|
||||
dmaChannelAllocate(LPC17xx_DAC_DMA_CHANNEL, \
|
||||
(lpc17xx_dmaisr_t)dac_serve_dma_interrupt, \
|
||||
(void *)dacp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_stop(DACDriver *dacp) {
|
||||
|
||||
/* If in ready state then disables the DAC clock.*/
|
||||
if (dacp->state == DAC_READY) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL);
|
||||
dmaChannelRelease(LPC17xx_DAC_DMA_CHANNEL);
|
||||
|
||||
/* Disable DAC */
|
||||
LPC_PINCON->PINSEL1 &= ~(2UL << 20); /* Disable AOUT P0.26 pin.*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the DAC bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start_conversion(DACDriver *dacp) {
|
||||
|
||||
dacp->half_buffer = false;
|
||||
uint32_t dma_ch_config;
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_dac_lli[0].srcaddr = (uint32_t) &dacp->samples[0];
|
||||
lpc_dac_lli[0].dstaddr = (uint32_t)&LPC_DAC->CR;
|
||||
lpc_dac_lli[0].lli = (uint32_t) &lpc_dac_lli[1];
|
||||
lpc_dac_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(dacp->depth/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_INC |
|
||||
DMA_CTRL_DST_NOINC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_dac_lli[1].srcaddr = (uint32_t) &dacp->samples[dacp->depth/2];
|
||||
lpc_dac_lli[1].dstaddr = lpc_dac_lli[0].dstaddr;
|
||||
lpc_dac_lli[1].control = lpc_dac_lli[0].control;
|
||||
|
||||
if (dacp->grpp->circular == true) {
|
||||
lpc_dac_lli[1].lli = (uint32_t) &lpc_dac_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_dac_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_DST_PERIPH(DMA_DAC) |
|
||||
DMA_CFG_TTYPE_M2P |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].lli);
|
||||
dmaChannelControl(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].control);
|
||||
dmaChannelConfig(LPC17xx_DAC_DMA_CHANNEL, dma_ch_config);
|
||||
|
||||
LPC_DAC->CTRL = DACCTRL_DMA_ENA | DACCTRL_CNT_ENA | DACCTRL_DBLBUF_ENA;
|
||||
}
|
||||
|
||||
void dac_lld_stop_conversion(DACDriver *dacp) {
|
||||
|
||||
/* If in active state then disables the DAC.*/
|
||||
if (dacp->state == DAC_ACTIVE) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/dac_lld.c
|
||||
* @brief LPC17xx DAC subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief CHN1 driver identifier.*/
|
||||
DACDriver DACD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc17xx_dma_lli_config_t lpc_dac_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief DAC DMA interrupt function.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] flags dma error flags
|
||||
*/
|
||||
static void dac_serve_dma_interrupt(DACDriver *dacp, uint32_t flags) {
|
||||
|
||||
if ((flags & (1 << LPC17xx_DAC_DMA_CHANNEL)) != 0) {
|
||||
_dac_isr_error_code(dacp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else {
|
||||
if (dacp->half_buffer == false) {
|
||||
_dac_isr_half_code(dacp);
|
||||
dacp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_dac_isr_full_code(dacp);
|
||||
dacp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level DAC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_init(void) {
|
||||
dacObjectInit(&DACD1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start(DACDriver *dacp) {
|
||||
|
||||
if (dacp->state == DAC_STOP) {
|
||||
|
||||
/* Enable DAC */
|
||||
LPC_PINCON->PINSEL1 |= (2UL << 20); /* Set AOUT P0.26 pin.*/
|
||||
|
||||
LPC_DAC->CR = 0;
|
||||
LPC_DAC->CTRL = 0;
|
||||
LPC_DAC->CNTVAL = LPC17xx_PCLK/dacp->config->frequency;
|
||||
|
||||
dmaChannelAllocate(LPC17xx_DAC_DMA_CHANNEL, \
|
||||
(lpc17xx_dmaisr_t)dac_serve_dma_interrupt, \
|
||||
(void *)dacp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_stop(DACDriver *dacp) {
|
||||
|
||||
/* If in ready state then disables the DAC clock.*/
|
||||
if (dacp->state == DAC_READY) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL);
|
||||
dmaChannelRelease(LPC17xx_DAC_DMA_CHANNEL);
|
||||
|
||||
/* Disable DAC */
|
||||
LPC_PINCON->PINSEL1 &= ~(2UL << 20); /* Disable AOUT P0.26 pin.*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the DAC bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start_conversion(DACDriver *dacp) {
|
||||
|
||||
dacp->half_buffer = false;
|
||||
uint32_t dma_ch_config;
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_dac_lli[0].srcaddr = (uint32_t) &dacp->samples[0];
|
||||
lpc_dac_lli[0].dstaddr = (uint32_t)&LPC_DAC->CR;
|
||||
lpc_dac_lli[0].lli = (uint32_t) &lpc_dac_lli[1];
|
||||
lpc_dac_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(dacp->depth/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_INC |
|
||||
DMA_CTRL_DST_NOINC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_dac_lli[1].srcaddr = (uint32_t) &dacp->samples[dacp->depth/2];
|
||||
lpc_dac_lli[1].dstaddr = lpc_dac_lli[0].dstaddr;
|
||||
lpc_dac_lli[1].control = lpc_dac_lli[0].control;
|
||||
|
||||
if (dacp->grpp->circular == true) {
|
||||
lpc_dac_lli[1].lli = (uint32_t) &lpc_dac_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_dac_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_DST_PERIPH(DMA_DAC) |
|
||||
DMA_CFG_TTYPE_M2P |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].lli);
|
||||
dmaChannelControl(LPC17xx_DAC_DMA_CHANNEL, lpc_dac_lli[0].control);
|
||||
dmaChannelConfig(LPC17xx_DAC_DMA_CHANNEL, dma_ch_config);
|
||||
|
||||
LPC_DAC->CTRL = DACCTRL_DMA_ENA | DACCTRL_CNT_ENA | DACCTRL_DBLBUF_ENA;
|
||||
}
|
||||
|
||||
void dac_lld_stop_conversion(DACDriver *dacp) {
|
||||
|
||||
/* If in active state then disables the DAC.*/
|
||||
if (dacp->state == DAC_ACTIVE) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC17xx_DAC_DMA_CHANNEL);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,207 +1,207 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/dac_lld.h
|
||||
* @brief LPC17xx DAC subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _DAC_LLD_H_
|
||||
#define _DAC_LLD_H_
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DACR_BIAS (1UL << 16)
|
||||
|
||||
#define DACCTRL_INT_DMA_REQ (1UL << 0)
|
||||
#define DACCTRL_DBLBUF_ENA (1UL << 1)
|
||||
#define DACCTRL_CNT_ENA (1UL << 2)
|
||||
#define DACCTRL_DMA_ENA (1UL << 3)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA stream used for DAC CHN1 TX operations.
|
||||
* @note This option is only available on platforms with enhanced DMA.
|
||||
*/
|
||||
#if !defined(LPC17xx_DAC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_DAC_DMA_CHANNEL DMA_CHANNEL5
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(LPC17xx_DMA_REQUIRED)
|
||||
#define LPC17xx_DMA_REQUIRED
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct DACDriver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type representing a DAC sample.
|
||||
*/
|
||||
typedef uint32_t dacsample_t;
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacendcallback_t)(DACDriver *dacp, const dacsample_t * samples, size_t pos);
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacerrcallback_t)(DACDriver *dacp, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint16_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
dacendcallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrcallback_t error_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
bool circular;
|
||||
|
||||
} DACConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer frequency in Hz.
|
||||
*/
|
||||
uint32_t frequency;
|
||||
/* End of the mandatory fields.*/
|
||||
} DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct DACDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
const dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
uint16_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if DAC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* DAC_USE_WAIT */
|
||||
#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern DACDriver DACD1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dac_lld_init(void);
|
||||
void dac_lld_start(DACDriver *dacp);
|
||||
void dac_lld_stop(DACDriver *dacp);
|
||||
void dac_lld_start_conversion(DACDriver *dacp);
|
||||
void dac_lld_stop_conversion(DACDriver *dacp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
#endif /* _DAC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/dac_lld.h
|
||||
* @brief LPC17xx DAC subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _DAC_LLD_H_
|
||||
#define _DAC_LLD_H_
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DACR_BIAS (1UL << 16)
|
||||
|
||||
#define DACCTRL_INT_DMA_REQ (1UL << 0)
|
||||
#define DACCTRL_DBLBUF_ENA (1UL << 1)
|
||||
#define DACCTRL_CNT_ENA (1UL << 2)
|
||||
#define DACCTRL_DMA_ENA (1UL << 3)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA stream used for DAC CHN1 TX operations.
|
||||
* @note This option is only available on platforms with enhanced DMA.
|
||||
*/
|
||||
#if !defined(LPC17xx_DAC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_DAC_DMA_CHANNEL DMA_CHANNEL5
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(LPC17xx_DMA_REQUIRED)
|
||||
#define LPC17xx_DMA_REQUIRED
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct DACDriver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type representing a DAC sample.
|
||||
*/
|
||||
typedef uint32_t dacsample_t;
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacendcallback_t)(DACDriver *dacp, const dacsample_t * samples, size_t pos);
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacerrcallback_t)(DACDriver *dacp, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint16_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
dacendcallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrcallback_t error_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
bool circular;
|
||||
|
||||
} DACConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer frequency in Hz.
|
||||
*/
|
||||
uint32_t frequency;
|
||||
/* End of the mandatory fields.*/
|
||||
} DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct DACDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
const dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
uint16_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if DAC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* DAC_USE_WAIT */
|
||||
#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern DACDriver DACD1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dac_lld_init(void);
|
||||
void dac_lld_start(DACDriver *dacp);
|
||||
void dac_lld_stop(DACDriver *dacp);
|
||||
void dac_lld_start_conversion(DACDriver *dacp);
|
||||
void dac_lld_stop_conversion(DACDriver *dacp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
#endif /* _DAC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,338 +1,338 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/gpt_lld.c
|
||||
* @brief LPC17xx GPT subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver identifier.
|
||||
* @note The driver GPT1 allocates the complex timer TIM0 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM0 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver identifier.
|
||||
* @note The driver GPT2 allocates the timer TIM1 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM1 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver identifier.
|
||||
* @note The driver GPT3 allocates the timer TIM2 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM2 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver identifier.
|
||||
* @note The driver GPT4 allocates the timer TIM3 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM3 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Shared IRQ handler.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
*/
|
||||
static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/
|
||||
if (gptp->state == GPT_ONESHOT) {
|
||||
gptp->state = GPT_READY; /* Back in GPT_READY state. */
|
||||
gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
|
||||
}
|
||||
gptp->config->callback(gptp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
/**
|
||||
* @brief TIM0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector44) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
/**
|
||||
* @brief TIM1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector48) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
/**
|
||||
* @brief TIM2 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector4C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM2 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
/**
|
||||
* @brief TIM3 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector50) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM3 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level GPT driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_init(void) {
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
/* Driver initialization.*/
|
||||
GPTD1.tmr = LPC_TIM0;
|
||||
gptObjectInit(&GPTD1);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
/* Driver initialization.*/
|
||||
GPTD2.tmr = LPC_TIM1;
|
||||
gptObjectInit(&GPTD2);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
/* Driver initialization.*/
|
||||
GPTD3.tmr = LPC_TIM2;
|
||||
gptObjectInit(&GPTD3);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
/* Driver initialization.*/
|
||||
GPTD4.tmr = LPC_TIM3;
|
||||
gptObjectInit(&GPTD4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start(GPTDriver *gptp) {
|
||||
uint32_t pr;
|
||||
|
||||
if (gptp->state == GPT_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 1);
|
||||
nvicEnableVector(TIMER0_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 2);
|
||||
nvicEnableVector(TIMER1_IRQn, CORTEX_PRIORITY_MASK(3));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 22);
|
||||
nvicEnableVector(TIMER2_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 23);
|
||||
nvicEnableVector(TIMER3_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prescaler value calculation.*/
|
||||
pr = (uint16_t)((LPC17xx_PCLK/ gptp->config->frequency) - 1);
|
||||
chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC17xx_PCLK,
|
||||
"gpt_lld_start(), #1", "invalid frequency");
|
||||
|
||||
/* Timer configuration.*/
|
||||
gptp->tmr->PR = pr;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop(GPTDriver *gptp) {
|
||||
|
||||
if (gptp->state == GPT_READY) {
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
nvicDisableVector(TIMER0_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 1);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
nvicDisableVector(TIMER1_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 2);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
nvicDisableVector(TIMER2_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 22);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
nvicDisableVector(TIMER3_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 23);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in continuous mode.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval period in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR0 = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in one shot mode and waits for completion.
|
||||
* @details This function specifically polls the timer waiting for completion
|
||||
* in order to not have extra delays caused by interrupt servicing,
|
||||
* this function is only recommended for short delays.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval time interval in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR0 = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 4; /* Stop TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
while (gptp->tmr->TCR & 1)
|
||||
;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/gpt_lld.c
|
||||
* @brief LPC17xx GPT subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver identifier.
|
||||
* @note The driver GPT1 allocates the complex timer TIM0 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM0 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver identifier.
|
||||
* @note The driver GPT2 allocates the timer TIM1 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM1 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver identifier.
|
||||
* @note The driver GPT3 allocates the timer TIM2 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM2 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver identifier.
|
||||
* @note The driver GPT4 allocates the timer TIM3 when enabled.
|
||||
*/
|
||||
#if LPC17xx_GPT_USE_TIM3 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Shared IRQ handler.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
*/
|
||||
static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/
|
||||
if (gptp->state == GPT_ONESHOT) {
|
||||
gptp->state = GPT_READY; /* Back in GPT_READY state. */
|
||||
gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
|
||||
}
|
||||
gptp->config->callback(gptp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
/**
|
||||
* @brief TIM0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector44) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
/**
|
||||
* @brief TIM1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector48) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
/**
|
||||
* @brief TIM2 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector4C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM2 */
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
/**
|
||||
* @brief TIM3 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector50) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC17xx_GPT_USE_TIM3 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level GPT driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_init(void) {
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
/* Driver initialization.*/
|
||||
GPTD1.tmr = LPC_TIM0;
|
||||
gptObjectInit(&GPTD1);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
/* Driver initialization.*/
|
||||
GPTD2.tmr = LPC_TIM1;
|
||||
gptObjectInit(&GPTD2);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
/* Driver initialization.*/
|
||||
GPTD3.tmr = LPC_TIM2;
|
||||
gptObjectInit(&GPTD3);
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
/* Driver initialization.*/
|
||||
GPTD4.tmr = LPC_TIM3;
|
||||
gptObjectInit(&GPTD4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start(GPTDriver *gptp) {
|
||||
uint32_t pr;
|
||||
|
||||
if (gptp->state == GPT_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 1);
|
||||
nvicEnableVector(TIMER0_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 2);
|
||||
nvicEnableVector(TIMER1_IRQn, CORTEX_PRIORITY_MASK(3));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 22);
|
||||
nvicEnableVector(TIMER2_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
LPC_SC->PCONP |= (1UL << 23);
|
||||
nvicEnableVector(TIMER3_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prescaler value calculation.*/
|
||||
pr = (uint16_t)((LPC17xx_PCLK/ gptp->config->frequency) - 1);
|
||||
chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC17xx_PCLK,
|
||||
"gpt_lld_start(), #1", "invalid frequency");
|
||||
|
||||
/* Timer configuration.*/
|
||||
gptp->tmr->PR = pr;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop(GPTDriver *gptp) {
|
||||
|
||||
if (gptp->state == GPT_READY) {
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
nvicDisableVector(TIMER0_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 1);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
nvicDisableVector(TIMER1_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 2);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
nvicDisableVector(TIMER2_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 22);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
nvicDisableVector(TIMER3_IRQn);
|
||||
LPC_SC->PCONP &= ~(1UL << 23);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in continuous mode.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval period in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR0 = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in one shot mode and waits for completion.
|
||||
* @details This function specifically polls the timer waiting for completion
|
||||
* in order to not have extra delays caused by interrupt servicing,
|
||||
* this function is only recommended for short delays.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval time interval in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR0 = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 4; /* Stop TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
while (gptp->tmr->TCR & 1)
|
||||
;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,208 +1,208 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/gpt_lld.h
|
||||
* @brief LPC17xx GPT subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GPT_LLD_H_
|
||||
#define _GPT_LLD_H_
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT4 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM3) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM0_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM1_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM2_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM3_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC17xx_GPT_USE_TIM0 && !LPC17xx_GPT_USE_TIM1 && \
|
||||
!LPC17xx_GPT_USE_TIM2 && !LPC17xx_GPT_USE_TIM3
|
||||
#error "GPT driver activated but no CT peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
typedef uint32_t gptfreq_t;
|
||||
|
||||
/**
|
||||
* @brief GPT counter type.
|
||||
*/
|
||||
typedef uint32_t gptcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer clock in Hz.
|
||||
* @note The low level can use assertions in order to catch invalid
|
||||
* frequency specifications.
|
||||
*/
|
||||
gptfreq_t frequency;
|
||||
/**
|
||||
* @brief Timer callback pointer.
|
||||
* @note This callback is invoked on GPT counter events.
|
||||
*/
|
||||
gptcallback_t callback;
|
||||
/* End of the mandatory fields.*/
|
||||
} GPTConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT driver.
|
||||
*/
|
||||
struct GPTDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
gptstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const GPTConfig *config;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Timer base clock.
|
||||
*/
|
||||
uint32_t clock;
|
||||
/**
|
||||
* @brief Pointer to the CTxxBy registers block.
|
||||
*/
|
||||
LPC_TIM_TypeDef *tmr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void gpt_lld_init(void);
|
||||
void gpt_lld_start(GPTDriver *gptp);
|
||||
void gpt_lld_stop(GPTDriver *gptp);
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp);
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
#endif /* _GPT_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/gpt_lld.h
|
||||
* @brief LPC17xx GPT subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GPT_LLD_H_
|
||||
#define _GPT_LLD_H_
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT4 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_USE_TIM3) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_USE_TIM3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM0_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM1_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM2_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_GPT_TIM3_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC17xx_GPT_USE_TIM0 && !LPC17xx_GPT_USE_TIM1 && \
|
||||
!LPC17xx_GPT_USE_TIM2 && !LPC17xx_GPT_USE_TIM3
|
||||
#error "GPT driver activated but no CT peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
typedef uint32_t gptfreq_t;
|
||||
|
||||
/**
|
||||
* @brief GPT counter type.
|
||||
*/
|
||||
typedef uint32_t gptcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer clock in Hz.
|
||||
* @note The low level can use assertions in order to catch invalid
|
||||
* frequency specifications.
|
||||
*/
|
||||
gptfreq_t frequency;
|
||||
/**
|
||||
* @brief Timer callback pointer.
|
||||
* @note This callback is invoked on GPT counter events.
|
||||
*/
|
||||
gptcallback_t callback;
|
||||
/* End of the mandatory fields.*/
|
||||
} GPTConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT driver.
|
||||
*/
|
||||
struct GPTDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
gptstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const GPTConfig *config;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Timer base clock.
|
||||
*/
|
||||
uint32_t clock;
|
||||
/**
|
||||
* @brief Pointer to the CTxxBy registers block.
|
||||
*/
|
||||
LPC_TIM_TypeDef *tmr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM0 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM1 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM2 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_GPT_USE_TIM3 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void gpt_lld_init(void);
|
||||
void gpt_lld_start(GPTDriver *gptp);
|
||||
void gpt_lld_stop(GPTDriver *gptp);
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp);
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
#endif /* _GPT_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,158 +1,158 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/hal_lld.c
|
||||
* @brief LPC17xx HAL subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/**
|
||||
* @brief Register missing in NXP header file.
|
||||
*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level HAL driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void hal_lld_init(void) {
|
||||
|
||||
/* SysTick initialization using the system clock.*/
|
||||
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, CORTEX_PRIORITY_SYSTICK);
|
||||
SysTick->LOAD = LPC17xx_CCLK / CH_FREQUENCY - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk;
|
||||
|
||||
/* DWT cycle counter enable.*/
|
||||
SCS_DEMCR |= SCS_DEMCR_TRCENA;
|
||||
DWT_CTRL |= DWT_CTRL_CYCCNTENA;
|
||||
|
||||
#if defined(LPC17xx_DMA_REQUIRED)
|
||||
dmaInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LPC17xx clocks and PLL initialization.
|
||||
* @note All the involved constants come from the file @p board.h.
|
||||
* @note This function must be invoked only after the system reset.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void LPC17xx_clock_init(void) {
|
||||
|
||||
/* Flash wait states setting, the code takes care to not touch TBD bits.*/
|
||||
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~(0x0000000F << 12)) | (LPC17xx_FLASHCFG_FLASHTIM << 12);
|
||||
|
||||
/* System oscillator initialization if required.*/
|
||||
|
||||
#if LPC17xx_MAINOSC_ENABLE
|
||||
LPC_SC->SCS = (1 << 5) | (LPC17xx_OSCRANGE << 4); /* Enable Main oscillator */
|
||||
while (!(LPC_SC->SCS & (1 << 6)))
|
||||
; /* Wait for main oscillator to be ready */
|
||||
#endif
|
||||
|
||||
/* Peripheral clock divider initialization, must be set before enabling Main PLL (PLL0).
|
||||
Read errata sheet ES_LPC176x. */
|
||||
LPC_SC->PCLKSEL0 = LPC17xx_PCLKSEL0;
|
||||
LPC_SC->PCLKSEL1 = LPC17xx_PCLKSEL1;
|
||||
|
||||
LPC_SC->CCLKCFG = LPC17xx_CCLK_DIV - 1; /* Set CPU clock divider */
|
||||
|
||||
LPC_SC->CLKSRCSEL = LPC17xx_SYSCLK_SELECT; /* Select clock source for PLL0 if enabled or CPU */
|
||||
|
||||
#if LPC17xx_MAINPLL_ENABLE
|
||||
|
||||
/* PLL0 configuration and start */
|
||||
LPC_SC->PLL0CFG = (LPC17xx_PLL0CFG_NSEL0 << 16) | LPC17xx_PLL0CFG_MSEL0;
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
|
||||
LPC_SC->PLL0CON = 0x01; /* Enable PLL0. */
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
while (!(LPC_SC->PLL0STAT & (1UL << 26)))
|
||||
; /* Wait for PLL0 locked */
|
||||
|
||||
LPC_SC->PLL0CON = 0x03; /* Enable and Connect PLL0. */
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
while (!(LPC_SC->PLL0STAT & ((1UL << 25) | (1UL << 24))))
|
||||
; /* Wait for PLL0 connected */
|
||||
|
||||
#endif /* LPC17xx_MAINPLL_ENABLE == TRUE */
|
||||
|
||||
#if LPC17xx_USBPLL_ENABLE
|
||||
/* PLL1 configuration and start */
|
||||
LPC_SC->PLL1CFG = (LPC17xx_PLL1CFG_PSEL1 << 5) | LPC17xx_PLL1CFG_MSEL1;
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
|
||||
LPC_SC->PLL1CON = 0x01; /* Enable PLL1. */
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
while (!(LPC_SC->PLL1STAT & (1UL << 10)))
|
||||
; /* Wait for PLL1 locked */
|
||||
|
||||
LPC_SC->PLL1CON = 0x03; /* Enable and Connect PLL1. */
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
while (!(LPC_SC->PLL1STAT & ((1UL << 9) | (1UL << 8))))
|
||||
; /* Wait for PLL1 connected */
|
||||
#endif /* LPC17xx_USBPLL_ENABLE == TRUE */
|
||||
|
||||
#if !LPC17xx_USBPLL_ENABLE && HAL_USE_USB
|
||||
LPC_SC->USBCLKCFG = LPC17xx_USBCLKPLL0_SELECT;
|
||||
#endif
|
||||
|
||||
/* Power control configuration */
|
||||
LPC_SC->PCONP = (1 << 15) | (1 << 9); /* Enable power for GPIO and RTC */
|
||||
|
||||
#if LPC17xx_CLKOUT_ENABLE
|
||||
LPC_SC->CLKOUTCFG = (1UL << 8) | ((LPC17xx_CLKOUT_DIV - 1) << 4) | LPC17xx_CLKOUT_SELECT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/hal_lld.c
|
||||
* @brief LPC17xx HAL subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/**
|
||||
* @brief Register missing in NXP header file.
|
||||
*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level HAL driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void hal_lld_init(void) {
|
||||
|
||||
/* SysTick initialization using the system clock.*/
|
||||
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, CORTEX_PRIORITY_SYSTICK);
|
||||
SysTick->LOAD = LPC17xx_CCLK / CH_FREQUENCY - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk;
|
||||
|
||||
/* DWT cycle counter enable.*/
|
||||
SCS_DEMCR |= SCS_DEMCR_TRCENA;
|
||||
DWT_CTRL |= DWT_CTRL_CYCCNTENA;
|
||||
|
||||
#if defined(LPC17xx_DMA_REQUIRED)
|
||||
dmaInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LPC17xx clocks and PLL initialization.
|
||||
* @note All the involved constants come from the file @p board.h.
|
||||
* @note This function must be invoked only after the system reset.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void LPC17xx_clock_init(void) {
|
||||
|
||||
/* Flash wait states setting, the code takes care to not touch TBD bits.*/
|
||||
LPC_SC->FLASHCFG = (LPC_SC->FLASHCFG & ~(0x0000000F << 12)) | (LPC17xx_FLASHCFG_FLASHTIM << 12);
|
||||
|
||||
/* System oscillator initialization if required.*/
|
||||
|
||||
#if LPC17xx_MAINOSC_ENABLE
|
||||
LPC_SC->SCS = (1 << 5) | (LPC17xx_OSCRANGE << 4); /* Enable Main oscillator */
|
||||
while (!(LPC_SC->SCS & (1 << 6)))
|
||||
; /* Wait for main oscillator to be ready */
|
||||
#endif
|
||||
|
||||
/* Peripheral clock divider initialization, must be set before enabling Main PLL (PLL0).
|
||||
Read errata sheet ES_LPC176x. */
|
||||
LPC_SC->PCLKSEL0 = LPC17xx_PCLKSEL0;
|
||||
LPC_SC->PCLKSEL1 = LPC17xx_PCLKSEL1;
|
||||
|
||||
LPC_SC->CCLKCFG = LPC17xx_CCLK_DIV - 1; /* Set CPU clock divider */
|
||||
|
||||
LPC_SC->CLKSRCSEL = LPC17xx_SYSCLK_SELECT; /* Select clock source for PLL0 if enabled or CPU */
|
||||
|
||||
#if LPC17xx_MAINPLL_ENABLE
|
||||
|
||||
/* PLL0 configuration and start */
|
||||
LPC_SC->PLL0CFG = (LPC17xx_PLL0CFG_NSEL0 << 16) | LPC17xx_PLL0CFG_MSEL0;
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
|
||||
LPC_SC->PLL0CON = 0x01; /* Enable PLL0. */
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
while (!(LPC_SC->PLL0STAT & (1UL << 26)))
|
||||
; /* Wait for PLL0 locked */
|
||||
|
||||
LPC_SC->PLL0CON = 0x03; /* Enable and Connect PLL0. */
|
||||
LPC_SC->PLL0FEED = 0xAA;
|
||||
LPC_SC->PLL0FEED = 0x55;
|
||||
while (!(LPC_SC->PLL0STAT & ((1UL << 25) | (1UL << 24))))
|
||||
; /* Wait for PLL0 connected */
|
||||
|
||||
#endif /* LPC17xx_MAINPLL_ENABLE == TRUE */
|
||||
|
||||
#if LPC17xx_USBPLL_ENABLE
|
||||
/* PLL1 configuration and start */
|
||||
LPC_SC->PLL1CFG = (LPC17xx_PLL1CFG_PSEL1 << 5) | LPC17xx_PLL1CFG_MSEL1;
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
|
||||
LPC_SC->PLL1CON = 0x01; /* Enable PLL1. */
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
while (!(LPC_SC->PLL1STAT & (1UL << 10)))
|
||||
; /* Wait for PLL1 locked */
|
||||
|
||||
LPC_SC->PLL1CON = 0x03; /* Enable and Connect PLL1. */
|
||||
LPC_SC->PLL1FEED = 0xAA;
|
||||
LPC_SC->PLL1FEED = 0x55;
|
||||
while (!(LPC_SC->PLL1STAT & ((1UL << 9) | (1UL << 8))))
|
||||
; /* Wait for PLL1 connected */
|
||||
#endif /* LPC17xx_USBPLL_ENABLE == TRUE */
|
||||
|
||||
#if !LPC17xx_USBPLL_ENABLE && HAL_USE_USB
|
||||
LPC_SC->USBCLKCFG = LPC17xx_USBCLKPLL0_SELECT;
|
||||
#endif
|
||||
|
||||
/* Power control configuration */
|
||||
LPC_SC->PCONP = (1 << 15) | (1 << 9); /* Enable power for GPIO and RTC */
|
||||
|
||||
#if LPC17xx_CLKOUT_ENABLE
|
||||
LPC_SC->CLKOUTCFG = (1UL << 8) | ((LPC17xx_CLKOUT_DIV - 1) << 4) | LPC17xx_CLKOUT_SELECT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,433 +1,433 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/hal_lld.h
|
||||
* @brief HAL subsystem low level driver header template.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_LLD_H_
|
||||
#define _HAL_LLD_H_
|
||||
|
||||
#include "LPC17xx.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Defines the support for realtime counters in the HAL.
|
||||
*/
|
||||
#define HAL_IMPLEMENTS_COUNTERS TRUE
|
||||
|
||||
/**
|
||||
* @brief Platform name.
|
||||
*/
|
||||
#define PLATFORM_NAME "LPC17xx"
|
||||
|
||||
#define IRCOSCCLK 4000000UL /**< High speed internal clock. */
|
||||
|
||||
#define CLKSRCSEL_IRCOSC 0UL /**< Clock source is IRC. */
|
||||
#define CLKSRCSEL_MAINOSC 1UL /**< Clock source is Main oscillator. */
|
||||
#define CLKSRCSEL_RTCOSC 2UL /**< Clock source is RTC oscillator. */
|
||||
|
||||
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock source is CCLK/4 */
|
||||
#define PCLKSEL_CCLK 1UL /**< Peripheral clock source is CCLK */
|
||||
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock source is CCLK/2 */
|
||||
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock source is CCLK/8 */
|
||||
#define PCLKSEL_MASK 3UL
|
||||
|
||||
#define CLKOUTSEL_CCLK 0UL /**< Clock output is CPU clock. */
|
||||
#define CLKOUTSEL_MAINOSC 1UL /**< Clock output is Main oscillator. */
|
||||
#define CLKOUTSEL_IRCOSC 2UL /**< Clock output is IRC oscillator. */
|
||||
#define CLKOUTSEL_USBCLK 3UL /**< Clock output is USB clock. */
|
||||
#define CLKOUTSEL_RTCOSC 4UL /**< Clock output is RTC oscillator. */
|
||||
|
||||
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock output is CCLK/4 */
|
||||
#define PCLKSEL_CCLK 1UL /**< Peripheral clock output is CCLK */
|
||||
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock output is CCLK/2 */
|
||||
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock output is CCLK/8 */
|
||||
|
||||
#define USBSEL_PLL0_DIV_6 5UL /**< USB clock source is PLL0/6. */
|
||||
#define USBSEL_PLL0_DIV_7 7UL /**< USB clock source is PLL0/7. */
|
||||
#define USBSEL_PLL0_DIV_9 9UL /**< USB clock source is PLL0/9. */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Main oscillator enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINOSC_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINOSC_ENABLE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System PLL clock source select.
|
||||
*/
|
||||
#if !defined(LPC17xx_SYSCLK_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SYSCLK_SELECT CLKSRCSEL_MAINOSC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_ENABLE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL multiplier.
|
||||
* @note Final frequency must not exceed the CCO ratings.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_MUL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_MUL 200
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL pre-divider.
|
||||
* @note The value must be in the 1..32 range and the final frequency
|
||||
* must not exceed the CCO ratings.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_PREDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_PREDIV 6
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL multiplier.
|
||||
* @note The value must be in the 1..32 range and the final frequency
|
||||
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_MUL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_MUL 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL divider.
|
||||
* @note The value must be 2, 4, 8 or 16 and the final frequency
|
||||
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU clock divider.
|
||||
* @note The value must be chosen between (1...255).
|
||||
*/
|
||||
#if !defined(LPC17xx_CCLK_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CCLK_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PCLK clock select.
|
||||
*/
|
||||
#if !defined(LPC17xx_PCLK_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PCLK_SELECT PCLKSEL_CCLK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output enable.
|
||||
* @note
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output divider.
|
||||
* @note The value must be chosen between (1...16).
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output clock source select.
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_SELECT CLKOUTSEL_MAINOSC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB clock PPL0 clock source select.
|
||||
* @note PLL0 output must be 288MHz (USBSEL_PLL0_DIV_6), 384MHz (USBSEL_PLL0_DIV_8) or
|
||||
* 480MHz(USBSEL_PLL0_DIV_10). Only is used when USB PLL (PLL1) disable.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBCLKPLL0_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBCLKPLL0_SELECT USBSEL_PLL0_DIV_6
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Calculated OSCRANGE setting.
|
||||
*/
|
||||
#if (MAINOSCCLK < 18000000) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_OSCRANGE 0
|
||||
#else
|
||||
#define LPC17xx_OSCRANGE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PLL input clock frequency.
|
||||
*/
|
||||
#if (LPC17xx_SYSCLK_SELECT == CLKSRCSEL_IRCOSC) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SYSCLK IRCOSCCLK
|
||||
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_MAINOSC
|
||||
#define LPC17xx_SYSCLK MAINOSCCLK
|
||||
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_RTCOSC
|
||||
#define LPC17xx_SYSCLK RTCOSCCLK
|
||||
#else
|
||||
#error "Invalid LPC17xx_SYSCLK_SELECT clock source specified."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MSEL mask in SYSPLLCTRL register.
|
||||
*/
|
||||
#if ((LPC17xx_MAINPLL_MUL % 2) == 0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL0CFG_MSEL0 ((LPC17xx_MAINPLL_MUL/2) - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_PLL0CFG_MUL value."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PSEL mask in SYSPLLCTRL register.
|
||||
*/
|
||||
#if ((LPC17xx_MAINPLL_PREDIV >= 1) && (LPC17xx_MAINPLL_PREDIV <= 32)) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL0CFG_NSEL0 (LPC17xx_MAINPLL_PREDIV - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_MAINPLL_PREDIV value (1 to 32 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CCO frequency.
|
||||
*/
|
||||
#define LPC17xx_MAINPLLCCO ((LPC17xx_MAINPLL_MUL * \
|
||||
LPC17xx_SYSCLK)/LPC17xx_MAINPLL_PREDIV)
|
||||
|
||||
#if (LPC17xx_MAINPLLCCO < 275000000) || (LPC17xx_SYSPLLCCO > 550000000)
|
||||
#error "CCO frequency out of the acceptable range (275...550)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PLL output clock frequency.
|
||||
*/
|
||||
#if LPC17xx_MAINPLL_ENABLE
|
||||
#define LPC17xx_MAINPLLCLK LPC17xx_MAINPLLCCO
|
||||
#else
|
||||
#define LPC17xx_MAINPLLCLK LPC17xx_SYSCLK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU clock frequency.
|
||||
* @note Most of LPC17xx have max 120 MHz clock.
|
||||
*/
|
||||
#define LPC17xx_CCLK (LPC17xx_MAINPLLCLK/LPC17xx_CCLK_DIV)
|
||||
#if (LPC17xx_CCLK > 120000000) || defined(__DOXYGEN__)
|
||||
#error "CPU Clock out of range."
|
||||
#endif
|
||||
|
||||
#if LPC17xx_USBPLL_ENABLE
|
||||
/**
|
||||
* @brief Main oscillator out of range.
|
||||
*/
|
||||
#if ((MAINOSCCLK < 10000000) && (MAINOSCCLK > 25000000)) || defined(__DOXYGEN__)
|
||||
#error "Main oscillator clock out of range."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MSEL1 mask in PLL1CFG register.
|
||||
*/
|
||||
#if (LPC17xx_USBPLL_MUL >= 1) && (LPC17xx_USBPLL_MUL <= 32) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL1CFG_MSEL1 (LPC17xx_USBPLL_MUL - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_USBPLL_MUL value (1 to 32 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PSEL1 mask in PLL1CFG register.
|
||||
*/
|
||||
#if (LPC17xx_USBPLL_DIV == 2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 0UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 4)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 1UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 8)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 2UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 16)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 3UL
|
||||
#else
|
||||
#error "Invalid LPC17xx_USBPLL_DIV value (2, 4, 8, 16 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL CCO frequency.
|
||||
*/
|
||||
#define LPC17xx_USBPLLCCO (MAINOSCCLK * LPC17xx_USBPLL_MUL * \
|
||||
LPC17xx_USBPLL_DIV)
|
||||
|
||||
#if (LPC17xx_USBPLLCCO < 156000000) || (LPC17xx_SYSPLLCCO > 320000000)
|
||||
#error "CCO frequency out of the acceptable range (156...320)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB clock frequency.
|
||||
* @note Must be 48 MHz.
|
||||
*/
|
||||
#define LPC17xx_USBCLK (LPC17xx_USBPLLCCO/LPC17xx_USBPLL_DIV)
|
||||
#if (LPC17xx_USBCLK != 48000000) || defined(__DOXYGEN__)
|
||||
#error "USB clock out of range."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Peripheral clock frequency.
|
||||
*/
|
||||
#if (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_4) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/4)
|
||||
#define LPC17xx_PCLKSEL0 0x00
|
||||
#define LPC17xx_PCLKSEL1 0x00
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK)
|
||||
#define LPC17xx_PCLKSEL0 0x55515155
|
||||
#define LPC17xx_PCLKSEL1 0x54555455
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_2)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/2)
|
||||
#define LPC17xx_PCLKSEL0 0xAAA2A2AA
|
||||
#define LPC17xx_PCLKSEL1 0xA8AAA8AA
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_8)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/8)
|
||||
#define LPC17xx_PCLKSEL0 0xFFF3F3FF
|
||||
#define LPC17xx_PCLKSEL1 0xFCFFFCFF
|
||||
#else
|
||||
#error "Invalid LPC17xx_PCLK_SELECT value"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief LPC17xx_CLKOUT_DIV out of range.
|
||||
*/
|
||||
#if ((LPC17xx_CLKOUT_DIV < 1) && (LPC17xx_CLKOUT_DIV > 16)) || defined(__DOXYGEN__)
|
||||
#error "Invalid LPC17xx_CLKOUT_DIV value (1 to 16 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CLKOUT frequency.
|
||||
*/
|
||||
#if (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_CCLK) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUTCLK (LPC17xx_CCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_MAINOSC)
|
||||
#define LPC17xx_CLKOUTCLK (MAINOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_IRCOSC)
|
||||
#define LPC17xx_CLKOUTCLK (IRCOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_USBCLK)
|
||||
#define LPC17xx_CLKOUTCLK (LPC17xx_USBCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_RTCOSC)
|
||||
#define LPC17xx_CLKOUTCLK (RTCOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#else
|
||||
#error "Invalid LPC17xx_CLKOUT_SELECT value."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CLKOUT frequency out of range.
|
||||
*/
|
||||
#if (LPC17xx_CLKOUTCLK > 50000000) || defined(__DOXYGEN__)
|
||||
#error "CLKOUT frequency out of the acceptable range (less than 50 MHz)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Flash wait states.
|
||||
*/
|
||||
#if (LPC17xx_CCLK <= 20000000) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 0UL
|
||||
#elif LPC17xx_CCLK <= 40000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 1UL
|
||||
#elif LPC17xx_CCLK <= 60000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 2UL
|
||||
#elif LPC17xx_CCLK <= 80000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 3UL
|
||||
#elif LPC17xx_CCLK <= 120000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 4UL
|
||||
#else
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 5UL
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of the realtime free counter value.
|
||||
*/
|
||||
typedef uint32_t halrtcnt_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Returns the current value of the system free running counter.
|
||||
* @note This service is implemented by returning the content of the
|
||||
* DWT_CYCCNT register.
|
||||
*
|
||||
* @return The value of the system free running counter of
|
||||
* type halrtcnt_t.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define hal_lld_get_counter_value() DWT_CYCCNT
|
||||
|
||||
/**
|
||||
* @brief Realtime counter frequency.
|
||||
* @note The DWT_CYCCNT register is incremented directly by the cpu
|
||||
* clock so this function returns LPC17xx_CCLK.
|
||||
*
|
||||
* @return The realtime counter frequency of type halclock_t.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define hal_lld_get_counter_frequency() LPC17xx_CCLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#include "lpc17xx_dma.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void hal_lld_init(void);
|
||||
void LPC17xx_clock_init(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/hal_lld.h
|
||||
* @brief HAL subsystem low level driver header template.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _HAL_LLD_H_
|
||||
#define _HAL_LLD_H_
|
||||
|
||||
#include "LPC17xx.h"
|
||||
#include "nvic.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Defines the support for realtime counters in the HAL.
|
||||
*/
|
||||
#define HAL_IMPLEMENTS_COUNTERS TRUE
|
||||
|
||||
/**
|
||||
* @brief Platform name.
|
||||
*/
|
||||
#define PLATFORM_NAME "LPC17xx"
|
||||
|
||||
#define IRCOSCCLK 4000000UL /**< High speed internal clock. */
|
||||
|
||||
#define CLKSRCSEL_IRCOSC 0UL /**< Clock source is IRC. */
|
||||
#define CLKSRCSEL_MAINOSC 1UL /**< Clock source is Main oscillator. */
|
||||
#define CLKSRCSEL_RTCOSC 2UL /**< Clock source is RTC oscillator. */
|
||||
|
||||
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock source is CCLK/4 */
|
||||
#define PCLKSEL_CCLK 1UL /**< Peripheral clock source is CCLK */
|
||||
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock source is CCLK/2 */
|
||||
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock source is CCLK/8 */
|
||||
#define PCLKSEL_MASK 3UL
|
||||
|
||||
#define CLKOUTSEL_CCLK 0UL /**< Clock output is CPU clock. */
|
||||
#define CLKOUTSEL_MAINOSC 1UL /**< Clock output is Main oscillator. */
|
||||
#define CLKOUTSEL_IRCOSC 2UL /**< Clock output is IRC oscillator. */
|
||||
#define CLKOUTSEL_USBCLK 3UL /**< Clock output is USB clock. */
|
||||
#define CLKOUTSEL_RTCOSC 4UL /**< Clock output is RTC oscillator. */
|
||||
|
||||
#define PCLKSEL_CCLK_DIV_4 0UL /**< Peripheral clock output is CCLK/4 */
|
||||
#define PCLKSEL_CCLK 1UL /**< Peripheral clock output is CCLK */
|
||||
#define PCLKSEL_CCLK_DIV_2 2UL /**< Peripheral clock output is CCLK/2 */
|
||||
#define PCLKSEL_CCLK_DIV_8 3UL /**< Peripheral clock output is CCLK/8 */
|
||||
|
||||
#define USBSEL_PLL0_DIV_6 5UL /**< USB clock source is PLL0/6. */
|
||||
#define USBSEL_PLL0_DIV_7 7UL /**< USB clock source is PLL0/7. */
|
||||
#define USBSEL_PLL0_DIV_9 9UL /**< USB clock source is PLL0/9. */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Main oscillator enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINOSC_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINOSC_ENABLE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System PLL clock source select.
|
||||
*/
|
||||
#if !defined(LPC17xx_SYSCLK_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SYSCLK_SELECT CLKSRCSEL_MAINOSC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_ENABLE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL multiplier.
|
||||
* @note Final frequency must not exceed the CCO ratings.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_MUL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_MUL 200
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main PLL pre-divider.
|
||||
* @note The value must be in the 1..32 range and the final frequency
|
||||
* must not exceed the CCO ratings.
|
||||
*/
|
||||
#if !defined(LPC17xx_MAINPLL_PREDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_MAINPLL_PREDIV 6
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL multiplier.
|
||||
* @note The value must be in the 1..32 range and the final frequency
|
||||
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_MUL) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_MUL 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL divider.
|
||||
* @note The value must be 2, 4, 8 or 16 and the final frequency
|
||||
* must not exceed the CCO ratings and USB clock must be equal 48MHz.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBPLL_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBPLL_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU clock divider.
|
||||
* @note The value must be chosen between (1...255).
|
||||
*/
|
||||
#if !defined(LPC17xx_CCLK_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CCLK_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PCLK clock select.
|
||||
*/
|
||||
#if !defined(LPC17xx_PCLK_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PCLK_SELECT PCLKSEL_CCLK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output enable.
|
||||
* @note
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_ENABLE) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output divider.
|
||||
* @note The value must be chosen between (1...16).
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_DIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_DIV 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock output clock source select.
|
||||
*/
|
||||
#if !defined(LPC17xx_CLKOUT_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUT_SELECT CLKOUTSEL_MAINOSC
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB clock PPL0 clock source select.
|
||||
* @note PLL0 output must be 288MHz (USBSEL_PLL0_DIV_6), 384MHz (USBSEL_PLL0_DIV_8) or
|
||||
* 480MHz(USBSEL_PLL0_DIV_10). Only is used when USB PLL (PLL1) disable.
|
||||
*/
|
||||
#if !defined(LPC17xx_USBCLKPLL0_SELECT) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_USBCLKPLL0_SELECT USBSEL_PLL0_DIV_6
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Calculated OSCRANGE setting.
|
||||
*/
|
||||
#if (MAINOSCCLK < 18000000) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_OSCRANGE 0
|
||||
#else
|
||||
#define LPC17xx_OSCRANGE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PLL input clock frequency.
|
||||
*/
|
||||
#if (LPC17xx_SYSCLK_SELECT == CLKSRCSEL_IRCOSC) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SYSCLK IRCOSCCLK
|
||||
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_MAINOSC
|
||||
#define LPC17xx_SYSCLK MAINOSCCLK
|
||||
#elif LPC17xx_SYSCLK_SELECT == CLKSRCSEL_RTCOSC
|
||||
#define LPC17xx_SYSCLK RTCOSCCLK
|
||||
#else
|
||||
#error "Invalid LPC17xx_SYSCLK_SELECT clock source specified."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MSEL mask in SYSPLLCTRL register.
|
||||
*/
|
||||
#if ((LPC17xx_MAINPLL_MUL % 2) == 0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL0CFG_MSEL0 ((LPC17xx_MAINPLL_MUL/2) - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_PLL0CFG_MUL value."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PSEL mask in SYSPLLCTRL register.
|
||||
*/
|
||||
#if ((LPC17xx_MAINPLL_PREDIV >= 1) && (LPC17xx_MAINPLL_PREDIV <= 32)) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL0CFG_NSEL0 (LPC17xx_MAINPLL_PREDIV - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_MAINPLL_PREDIV value (1 to 32 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CCO frequency.
|
||||
*/
|
||||
#define LPC17xx_MAINPLLCCO ((LPC17xx_MAINPLL_MUL * \
|
||||
LPC17xx_SYSCLK)/LPC17xx_MAINPLL_PREDIV)
|
||||
|
||||
#if (LPC17xx_MAINPLLCCO < 275000000) || (LPC17xx_SYSPLLCCO > 550000000)
|
||||
#error "CCO frequency out of the acceptable range (275...550)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PLL output clock frequency.
|
||||
*/
|
||||
#if LPC17xx_MAINPLL_ENABLE
|
||||
#define LPC17xx_MAINPLLCLK LPC17xx_MAINPLLCCO
|
||||
#else
|
||||
#define LPC17xx_MAINPLLCLK LPC17xx_SYSCLK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU clock frequency.
|
||||
* @note Most of LPC17xx have max 120 MHz clock.
|
||||
*/
|
||||
#define LPC17xx_CCLK (LPC17xx_MAINPLLCLK/LPC17xx_CCLK_DIV)
|
||||
#if (LPC17xx_CCLK > 120000000) || defined(__DOXYGEN__)
|
||||
#error "CPU Clock out of range."
|
||||
#endif
|
||||
|
||||
#if LPC17xx_USBPLL_ENABLE
|
||||
/**
|
||||
* @brief Main oscillator out of range.
|
||||
*/
|
||||
#if ((MAINOSCCLK < 10000000) && (MAINOSCCLK > 25000000)) || defined(__DOXYGEN__)
|
||||
#error "Main oscillator clock out of range."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MSEL1 mask in PLL1CFG register.
|
||||
*/
|
||||
#if (LPC17xx_USBPLL_MUL >= 1) && (LPC17xx_USBPLL_MUL <= 32) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL1CFG_MSEL1 (LPC17xx_USBPLL_MUL - 1)
|
||||
#else
|
||||
#error "Invalid LPC17xx_USBPLL_MUL value (1 to 32 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PSEL1 mask in PLL1CFG register.
|
||||
*/
|
||||
#if (LPC17xx_USBPLL_DIV == 2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 0UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 4)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 1UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 8)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 2UL
|
||||
#elif (LPC17xx_USBPLL_DIV == 16)
|
||||
#define LPC17xx_PLL1CFG_PSEL1 3UL
|
||||
#else
|
||||
#error "Invalid LPC17xx_USBPLL_DIV value (2, 4, 8, 16 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB PLL CCO frequency.
|
||||
*/
|
||||
#define LPC17xx_USBPLLCCO (MAINOSCCLK * LPC17xx_USBPLL_MUL * \
|
||||
LPC17xx_USBPLL_DIV)
|
||||
|
||||
#if (LPC17xx_USBPLLCCO < 156000000) || (LPC17xx_SYSPLLCCO > 320000000)
|
||||
#error "CCO frequency out of the acceptable range (156...320)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief USB clock frequency.
|
||||
* @note Must be 48 MHz.
|
||||
*/
|
||||
#define LPC17xx_USBCLK (LPC17xx_USBPLLCCO/LPC17xx_USBPLL_DIV)
|
||||
#if (LPC17xx_USBCLK != 48000000) || defined(__DOXYGEN__)
|
||||
#error "USB clock out of range."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Peripheral clock frequency.
|
||||
*/
|
||||
#if (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_4) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/4)
|
||||
#define LPC17xx_PCLKSEL0 0x00
|
||||
#define LPC17xx_PCLKSEL1 0x00
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK)
|
||||
#define LPC17xx_PCLKSEL0 0x55515155
|
||||
#define LPC17xx_PCLKSEL1 0x54555455
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_2)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/2)
|
||||
#define LPC17xx_PCLKSEL0 0xAAA2A2AA
|
||||
#define LPC17xx_PCLKSEL1 0xA8AAA8AA
|
||||
#elif (LPC17xx_PCLK_SELECT == PCLKSEL_CCLK_DIV_8)
|
||||
#define LPC17xx_PCLK (LPC17xx_CCLK/8)
|
||||
#define LPC17xx_PCLKSEL0 0xFFF3F3FF
|
||||
#define LPC17xx_PCLKSEL1 0xFCFFFCFF
|
||||
#else
|
||||
#error "Invalid LPC17xx_PCLK_SELECT value"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief LPC17xx_CLKOUT_DIV out of range.
|
||||
*/
|
||||
#if ((LPC17xx_CLKOUT_DIV < 1) && (LPC17xx_CLKOUT_DIV > 16)) || defined(__DOXYGEN__)
|
||||
#error "Invalid LPC17xx_CLKOUT_DIV value (1 to 16 accepted)."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CLKOUT frequency.
|
||||
*/
|
||||
#if (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_CCLK) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_CLKOUTCLK (LPC17xx_CCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_MAINOSC)
|
||||
#define LPC17xx_CLKOUTCLK (MAINOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_IRCOSC)
|
||||
#define LPC17xx_CLKOUTCLK (IRCOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_USBCLK)
|
||||
#define LPC17xx_CLKOUTCLK (LPC17xx_USBCLK/LPC17xx_CLKOUT_DIV)
|
||||
#elif (LPC17xx_CLKOUT_SELECT == CLKOUTSEL_RTCOSC)
|
||||
#define LPC17xx_CLKOUTCLK (RTCOSCCLK/LPC17xx_CLKOUT_DIV)
|
||||
#else
|
||||
#error "Invalid LPC17xx_CLKOUT_SELECT value."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CLKOUT frequency out of range.
|
||||
*/
|
||||
#if (LPC17xx_CLKOUTCLK > 50000000) || defined(__DOXYGEN__)
|
||||
#error "CLKOUT frequency out of the acceptable range (less than 50 MHz)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Flash wait states.
|
||||
*/
|
||||
#if (LPC17xx_CCLK <= 20000000) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 0UL
|
||||
#elif LPC17xx_CCLK <= 40000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 1UL
|
||||
#elif LPC17xx_CCLK <= 60000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 2UL
|
||||
#elif LPC17xx_CCLK <= 80000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 3UL
|
||||
#elif LPC17xx_CCLK <= 120000000
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 4UL
|
||||
#else
|
||||
#define LPC17xx_FLASHCFG_FLASHTIM 5UL
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of the realtime free counter value.
|
||||
*/
|
||||
typedef uint32_t halrtcnt_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Returns the current value of the system free running counter.
|
||||
* @note This service is implemented by returning the content of the
|
||||
* DWT_CYCCNT register.
|
||||
*
|
||||
* @return The value of the system free running counter of
|
||||
* type halrtcnt_t.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define hal_lld_get_counter_value() DWT_CYCCNT
|
||||
|
||||
/**
|
||||
* @brief Realtime counter frequency.
|
||||
* @note The DWT_CYCCNT register is incremented directly by the cpu
|
||||
* clock so this function returns LPC17xx_CCLK.
|
||||
*
|
||||
* @return The realtime counter frequency of type halclock_t.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define hal_lld_get_counter_frequency() LPC17xx_CCLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#include "lpc17xx_dma.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void hal_lld_init(void);
|
||||
void LPC17xx_clock_init(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,271 +1,271 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx I2C driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/i2c_lld.h
|
||||
* @brief LPC17xx I2C subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _I2C_LLD_H_
|
||||
#define _I2C_LLD_H_
|
||||
|
||||
#if HAL_USE_I2C || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define I2C_CONSET_AA 0x04 /* Assert acknowledge flag. */
|
||||
#define I2C_CONSET_SI 0x08 /* I2C interrupt flag. */
|
||||
#define I2C_CONSET_STO 0x10 /* STOP flag. */
|
||||
#define I2C_CONSET_STA 0x20 /* START flag. */
|
||||
#define I2C_CONSET_EN 0x40 /* I2C interface enable. */
|
||||
|
||||
#define I2C_CONCLR_AAC 0x04 /* Assert acknowledge Clear bit. */
|
||||
#define I2C_CONCLR_SIC 0x08 /* I2C interrupt Clear bit. */
|
||||
#define I2C_CONCLR_STAC 0x20 /* START flag Clear bit. */
|
||||
#define I2C_CONCLR_ENC 0x40 /* I2C interface Disable bit. */
|
||||
|
||||
#define I2C_WR_BIT 0x00
|
||||
#define I2C_RD_BIT 0x01
|
||||
|
||||
#define I2C_STATE_MS_START 0x08
|
||||
#define I2C_STATE_MS_RSTART 0x10
|
||||
#define I2C_STATE_MS_SLAW_ACK 0x18
|
||||
#define I2C_STATE_MS_SLAW_NACK 0x20
|
||||
#define I2C_STATE_MS_TDAT_ACK 0x28
|
||||
#define I2C_STATE_MS_TDAT_NACK 0x30
|
||||
#define I2C_STATE_ARB_LOST 0x38
|
||||
|
||||
#define I2C_STATE_MS_SLAR_ACK 0x40
|
||||
#define I2C_STATE_MS_SLAR_NACK 0x48
|
||||
#define I2C_STATE_MS_RDAT_ACK 0x50
|
||||
#define I2C_STATE_MS_RDAT_NACK 0x58
|
||||
|
||||
#define I2C_STATE_BUS_ERROR 0x00
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief I2C0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C2 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type representing I2C address.
|
||||
*/
|
||||
typedef uint16_t i2caddr_t;
|
||||
|
||||
/**
|
||||
* @brief I2C Driver condition flags type.
|
||||
*/
|
||||
typedef uint32_t i2cflags_t;
|
||||
/**
|
||||
* @brief Supported modes for the I2C bus.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_STANDARD_MODE = 1,
|
||||
I2C_FAST_MODE = 2,
|
||||
I2C_FAST_MODE_PLUS = 3,
|
||||
} i2cmode_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
i2cmode_t mode; /**< @brief Specifies the I2C mode. */
|
||||
uint32_t clock_timing; /**< @brief Specifies the clock timing */
|
||||
} I2CConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an I2C driver.
|
||||
*/
|
||||
typedef struct I2CDriver I2CDriver;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an I2C driver.
|
||||
*/
|
||||
struct I2CDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
i2cstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const I2CConfig *config;
|
||||
/**
|
||||
* @brief Error flags.
|
||||
*/
|
||||
i2cflags_t errors;
|
||||
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* I2C_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(I2C_DRIVER_EXT_FIELDS)
|
||||
I2C_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Thread waiting for I/O completion.
|
||||
*/
|
||||
Thread *thread;
|
||||
/**
|
||||
* @brief Current slave address without R/W bit.
|
||||
*/
|
||||
i2caddr_t addr;
|
||||
/**
|
||||
* @brief Pointer to the transmit buffer.
|
||||
*/
|
||||
const uint8_t *txbuf;
|
||||
/**
|
||||
* @brief Number of bytes to transmit.
|
||||
*/
|
||||
size_t txbytes;
|
||||
/**
|
||||
* @brief Pointer to the receive buffer.
|
||||
*/
|
||||
uint8_t *rxbuf;
|
||||
/**
|
||||
* @brief Number of bytes to receive.
|
||||
*/
|
||||
size_t rxbytes;
|
||||
/**
|
||||
* @brief Pointer to the I2C registers block.
|
||||
*/
|
||||
LPC_I2C_TypeDef *i2c;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Get errors from I2C driver.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C0 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C1 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C2 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD3;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void i2c_lld_init(void);
|
||||
void i2c_lld_start(I2CDriver *i2cp);
|
||||
void i2c_lld_stop(I2CDriver *i2cp);
|
||||
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _I2C_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx I2C driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/i2c_lld.h
|
||||
* @brief LPC17xx I2C subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _I2C_LLD_H_
|
||||
#define _I2C_LLD_H_
|
||||
|
||||
#if HAL_USE_I2C || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define I2C_CONSET_AA 0x04 /* Assert acknowledge flag. */
|
||||
#define I2C_CONSET_SI 0x08 /* I2C interrupt flag. */
|
||||
#define I2C_CONSET_STO 0x10 /* STOP flag. */
|
||||
#define I2C_CONSET_STA 0x20 /* START flag. */
|
||||
#define I2C_CONSET_EN 0x40 /* I2C interface enable. */
|
||||
|
||||
#define I2C_CONCLR_AAC 0x04 /* Assert acknowledge Clear bit. */
|
||||
#define I2C_CONCLR_SIC 0x08 /* I2C interrupt Clear bit. */
|
||||
#define I2C_CONCLR_STAC 0x20 /* START flag Clear bit. */
|
||||
#define I2C_CONCLR_ENC 0x40 /* I2C interface Disable bit. */
|
||||
|
||||
#define I2C_WR_BIT 0x00
|
||||
#define I2C_RD_BIT 0x01
|
||||
|
||||
#define I2C_STATE_MS_START 0x08
|
||||
#define I2C_STATE_MS_RSTART 0x10
|
||||
#define I2C_STATE_MS_SLAW_ACK 0x18
|
||||
#define I2C_STATE_MS_SLAW_NACK 0x20
|
||||
#define I2C_STATE_MS_TDAT_ACK 0x28
|
||||
#define I2C_STATE_MS_TDAT_NACK 0x30
|
||||
#define I2C_STATE_ARB_LOST 0x38
|
||||
|
||||
#define I2C_STATE_MS_SLAR_ACK 0x40
|
||||
#define I2C_STATE_MS_SLAR_NACK 0x48
|
||||
#define I2C_STATE_MS_RDAT_ACK 0x50
|
||||
#define I2C_STATE_MS_RDAT_NACK 0x58
|
||||
|
||||
#define I2C_STATE_BUS_ERROR 0x00
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief I2C0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_USE_I2C2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_USE_I2C2 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_I2C_I2C2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type representing I2C address.
|
||||
*/
|
||||
typedef uint16_t i2caddr_t;
|
||||
|
||||
/**
|
||||
* @brief I2C Driver condition flags type.
|
||||
*/
|
||||
typedef uint32_t i2cflags_t;
|
||||
/**
|
||||
* @brief Supported modes for the I2C bus.
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_STANDARD_MODE = 1,
|
||||
I2C_FAST_MODE = 2,
|
||||
I2C_FAST_MODE_PLUS = 3,
|
||||
} i2cmode_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
i2cmode_t mode; /**< @brief Specifies the I2C mode. */
|
||||
uint32_t clock_timing; /**< @brief Specifies the clock timing */
|
||||
} I2CConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an I2C driver.
|
||||
*/
|
||||
typedef struct I2CDriver I2CDriver;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an I2C driver.
|
||||
*/
|
||||
struct I2CDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
i2cstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const I2CConfig *config;
|
||||
/**
|
||||
* @brief Error flags.
|
||||
*/
|
||||
i2cflags_t errors;
|
||||
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* I2C_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(I2C_DRIVER_EXT_FIELDS)
|
||||
I2C_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Thread waiting for I/O completion.
|
||||
*/
|
||||
Thread *thread;
|
||||
/**
|
||||
* @brief Current slave address without R/W bit.
|
||||
*/
|
||||
i2caddr_t addr;
|
||||
/**
|
||||
* @brief Pointer to the transmit buffer.
|
||||
*/
|
||||
const uint8_t *txbuf;
|
||||
/**
|
||||
* @brief Number of bytes to transmit.
|
||||
*/
|
||||
size_t txbytes;
|
||||
/**
|
||||
* @brief Pointer to the receive buffer.
|
||||
*/
|
||||
uint8_t *rxbuf;
|
||||
/**
|
||||
* @brief Number of bytes to receive.
|
||||
*/
|
||||
size_t rxbytes;
|
||||
/**
|
||||
* @brief Pointer to the I2C registers block.
|
||||
*/
|
||||
LPC_I2C_TypeDef *i2c;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Get errors from I2C driver.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C0 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C1 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_I2C_USE_I2C2 && !defined(__DOXYGEN__)
|
||||
extern I2CDriver I2CD3;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void i2c_lld_init(void);
|
||||
void i2c_lld_start(I2CDriver *i2cp);
|
||||
void i2c_lld_stop(I2CDriver *i2cp);
|
||||
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _I2C_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,205 +1,205 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/LPC17xx_dma.c
|
||||
* @brief DMA driver code.
|
||||
*
|
||||
* @addtogroup LPC17xx_DMA
|
||||
* @details DMA sharing helper driver. In the LPC17xx the DMA streams are a
|
||||
* shared resource, this driver allows to allocate and free DMA
|
||||
* streams at runtime in order to allow all the other device
|
||||
* drivers to coordinate the access to the resource.
|
||||
* @note The DMA ISR handlers are all declared into this module because
|
||||
* sharing, the various device drivers can associate a callback to
|
||||
* ISRs when allocating streams.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/* The following macro is only defined if some driver requiring DMA services
|
||||
has been enabled.*/
|
||||
#if defined(LPC17xx_DMA_REQUIRED) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
LPC_GPDMACH_TypeDef * \
|
||||
_lpc17xx_dma_channel_config_t[LPC17xx_DMA_CHANNELS] = {
|
||||
LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4,
|
||||
LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7 };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA ISR redirector type.
|
||||
*/
|
||||
typedef struct {
|
||||
lpc17xx_dmaisr_t dma_func; /**< @brief DMA callback function. */
|
||||
void *dma_param; /**< @brief DMA callback parameter. */
|
||||
} dma_isr_redir_t;
|
||||
|
||||
/**
|
||||
* @brief Mask of the allocated streams.
|
||||
*/
|
||||
static uint32_t dma_streams_mask;
|
||||
|
||||
/**
|
||||
* @brief DMA IRQ redirectors.
|
||||
*/
|
||||
static dma_isr_redir_t dma_isr_redir[LPC17xx_DMA_CHANNELS];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(VectorA8) {
|
||||
uint32_t irq_status;
|
||||
uint32_t err_status;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
irq_status = LPC_GPDMA->IntTCStat;
|
||||
LPC_GPDMA->IntTCClear = irq_status; /* Clear DMA interrupt flag */
|
||||
err_status = LPC_GPDMA->IntErrStat;
|
||||
LPC_GPDMA->IntErrClr = err_status; /* Clear DMA error flag if any*/
|
||||
|
||||
for (i = 0; i < LPC17xx_DMA_CHANNELS; i++) {
|
||||
if (irq_status & (1UL << i)) {
|
||||
if (dma_isr_redir[i].dma_func)
|
||||
dma_isr_redir[i].dma_func(dma_isr_redir[i].dma_param, err_status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx DMA initialization.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dmaInit(void) {
|
||||
uint8_t i;
|
||||
|
||||
LPC_SC->PCONP |= (1UL << 29); /* Enable DMA power */
|
||||
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < LPC17xx_DMA_CHANNELS; i++)
|
||||
_lpc17xx_dma_channel_config_t[i]->CConfig = 0;
|
||||
|
||||
LPC_GPDMA->IntTCClear = 0xFF;
|
||||
LPC_GPDMA->IntErrClr = 0xFF;
|
||||
|
||||
LPC_GPDMA->Config = DMACCONFIG_E; /* Enable DMA Controller */
|
||||
while((LPC_GPDMA->Config & DMACCONFIG_E) != 0x01)
|
||||
;
|
||||
|
||||
nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_DMA_IRQ_PRIORITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated.
|
||||
* @pre The channel must not be already in use or an error is returned.
|
||||
* @post The channel is allocated and the default ISR handler redirected
|
||||
* to the specified function.
|
||||
* @post The channel must be freed using @p dmaChannelRelease() before it can
|
||||
* be reused with another peripheral.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return The operation status.
|
||||
* @retval FALSE no error, stream taken.
|
||||
* @retval TRUE error, stream already taken.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
bool_t dmaChannelAllocate(lpc17xx_dma_channel_t dmach,
|
||||
lpc17xx_dmaisr_t func,
|
||||
void *param) {
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Checks if the channel is already taken.*/
|
||||
if ((dma_streams_mask & channel) != 0)
|
||||
return TRUE;
|
||||
|
||||
/* Marks the stream as allocated.*/
|
||||
dma_isr_redir[dmach].dma_func = func;
|
||||
dma_isr_redir[dmach].dma_param = param;
|
||||
dma_streams_mask |= channel;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post The channel is again available.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void dmaChannelRelease(lpc17xx_dma_channel_t dmach) {
|
||||
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Check if the streams is not taken.*/
|
||||
chDbgAssert((dma_streams_mask & channel) != 0,
|
||||
"dmaStreamRelease(), #1", "not allocated");
|
||||
|
||||
dma_streams_mask &= ~channel; /* Marks the stream as not allocated.*/
|
||||
}
|
||||
|
||||
#endif /* LPC17xx_DMA_REQUIRED */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/LPC17xx_dma.c
|
||||
* @brief DMA driver code.
|
||||
*
|
||||
* @addtogroup LPC17xx_DMA
|
||||
* @details DMA sharing helper driver. In the LPC17xx the DMA streams are a
|
||||
* shared resource, this driver allows to allocate and free DMA
|
||||
* streams at runtime in order to allow all the other device
|
||||
* drivers to coordinate the access to the resource.
|
||||
* @note The DMA ISR handlers are all declared into this module because
|
||||
* sharing, the various device drivers can associate a callback to
|
||||
* ISRs when allocating streams.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/* The following macro is only defined if some driver requiring DMA services
|
||||
has been enabled.*/
|
||||
#if defined(LPC17xx_DMA_REQUIRED) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
LPC_GPDMACH_TypeDef * \
|
||||
_lpc17xx_dma_channel_config_t[LPC17xx_DMA_CHANNELS] = {
|
||||
LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4,
|
||||
LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7 };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA ISR redirector type.
|
||||
*/
|
||||
typedef struct {
|
||||
lpc17xx_dmaisr_t dma_func; /**< @brief DMA callback function. */
|
||||
void *dma_param; /**< @brief DMA callback parameter. */
|
||||
} dma_isr_redir_t;
|
||||
|
||||
/**
|
||||
* @brief Mask of the allocated streams.
|
||||
*/
|
||||
static uint32_t dma_streams_mask;
|
||||
|
||||
/**
|
||||
* @brief DMA IRQ redirectors.
|
||||
*/
|
||||
static dma_isr_redir_t dma_isr_redir[LPC17xx_DMA_CHANNELS];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(VectorA8) {
|
||||
uint32_t irq_status;
|
||||
uint32_t err_status;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
irq_status = LPC_GPDMA->IntTCStat;
|
||||
LPC_GPDMA->IntTCClear = irq_status; /* Clear DMA interrupt flag */
|
||||
err_status = LPC_GPDMA->IntErrStat;
|
||||
LPC_GPDMA->IntErrClr = err_status; /* Clear DMA error flag if any*/
|
||||
|
||||
for (i = 0; i < LPC17xx_DMA_CHANNELS; i++) {
|
||||
if (irq_status & (1UL << i)) {
|
||||
if (dma_isr_redir[i].dma_func)
|
||||
dma_isr_redir[i].dma_func(dma_isr_redir[i].dma_param, err_status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx DMA initialization.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dmaInit(void) {
|
||||
uint8_t i;
|
||||
|
||||
LPC_SC->PCONP |= (1UL << 29); /* Enable DMA power */
|
||||
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < LPC17xx_DMA_CHANNELS; i++)
|
||||
_lpc17xx_dma_channel_config_t[i]->CConfig = 0;
|
||||
|
||||
LPC_GPDMA->IntTCClear = 0xFF;
|
||||
LPC_GPDMA->IntErrClr = 0xFF;
|
||||
|
||||
LPC_GPDMA->Config = DMACCONFIG_E; /* Enable DMA Controller */
|
||||
while((LPC_GPDMA->Config & DMACCONFIG_E) != 0x01)
|
||||
;
|
||||
|
||||
nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_DMA_IRQ_PRIORITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated.
|
||||
* @pre The channel must not be already in use or an error is returned.
|
||||
* @post The channel is allocated and the default ISR handler redirected
|
||||
* to the specified function.
|
||||
* @post The channel must be freed using @p dmaChannelRelease() before it can
|
||||
* be reused with another peripheral.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return The operation status.
|
||||
* @retval FALSE no error, stream taken.
|
||||
* @retval TRUE error, stream already taken.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
bool_t dmaChannelAllocate(lpc17xx_dma_channel_t dmach,
|
||||
lpc17xx_dmaisr_t func,
|
||||
void *param) {
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Checks if the channel is already taken.*/
|
||||
if ((dma_streams_mask & channel) != 0)
|
||||
return TRUE;
|
||||
|
||||
/* Marks the stream as allocated.*/
|
||||
dma_isr_redir[dmach].dma_func = func;
|
||||
dma_isr_redir[dmach].dma_param = param;
|
||||
dma_streams_mask |= channel;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post The channel is again available.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void dmaChannelRelease(lpc17xx_dma_channel_t dmach) {
|
||||
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Check if the streams is not taken.*/
|
||||
chDbgAssert((dma_streams_mask & channel) != 0,
|
||||
"dmaStreamRelease(), #1", "not allocated");
|
||||
|
||||
dma_streams_mask &= ~channel; /* Marks the stream as not allocated.*/
|
||||
}
|
||||
|
||||
#endif /* LPC17xx_DMA_REQUIRED */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,422 +1,422 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/LPC17xx_dma.h
|
||||
* @brief DMA driver header.
|
||||
*
|
||||
* @addtogroup LPC17xx_DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LPC17xx_DMA_H_
|
||||
#define _LPC17xx_DMA_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DMACCONFIG_E (1UL << 0)
|
||||
#define DMACCONFIG_M (1UL << 1)
|
||||
|
||||
/**
|
||||
* @brief Total number of DMA streams.
|
||||
* @note This is the total number of streams among all the DMA units.
|
||||
*/
|
||||
#define LPC17xx_DMA_CHANNELS 8
|
||||
|
||||
/**
|
||||
* @name DMA control data configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA transfer size.
|
||||
*
|
||||
* @param[in] n DMA transfer size
|
||||
*/
|
||||
#define DMA_CTRL_TRANSFER_SIZE(n) (n)
|
||||
|
||||
/**
|
||||
* @brief DMA source burst size.
|
||||
*/
|
||||
#define DMA_CTRL_SRC_BSIZE_1 (0 << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_4 (1UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_8 (2UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_16 (3UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_32 (4UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_64 (5UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_128 (6UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_256 (7UL << 12)
|
||||
|
||||
/**
|
||||
* @brief DMA destination burst size.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_BSIZE_1 (0 << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_4 (1UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_8 (2UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_16 (3UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_32 (4UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_64 (5UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_128 (6UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_256 (7UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_WIDTH_BYTE (0 << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_HWORD (1UL << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_WORD (2UL << 18)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_WIDTH_BYTE (0 << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_HWORD (1UL << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_WORD (2UL << 21)
|
||||
|
||||
/**
|
||||
* @name DMA source increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_NOINC (0UL << 26)
|
||||
#define DMA_CTRL_SRC_INC (1UL << 26)
|
||||
|
||||
/**
|
||||
* @name DMA destination increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_NOINC (0UL << 27)
|
||||
#define DMA_CTRL_DST_INC (1UL << 27)
|
||||
|
||||
/**
|
||||
* @name DMA bus access bits.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_PROT1_USER (0 << 28)
|
||||
#define DMA_CTRL_PROT1_PRIV (1UL << 28)
|
||||
|
||||
#define DMA_CTRL_PROT2_NONBUFF (0 << 29)
|
||||
#define DMA_CTRL_PROT2_BUFF (1UL << 29)
|
||||
|
||||
#define DMA_CTRL_PROT3_NONCACHE (0 << 30)
|
||||
#define DMA_CTRL_PROT3_CACHE (1UL << 30)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA terminal count interrupt enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_INT (1UL << 31)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA channel enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_CH_ENABLE (1UL << 0)
|
||||
|
||||
/**
|
||||
* @brief Source peripheral.
|
||||
*
|
||||
* @param[in] source source peripheral
|
||||
*/
|
||||
#define DMA_CFG_SRC_PERIPH(src) ((src) << 1)
|
||||
|
||||
/**
|
||||
* @brief Destination peripheral.
|
||||
*
|
||||
* @param[in] destination destination peripheral
|
||||
*/
|
||||
#define DMA_CFG_DST_PERIPH(dst) ((dst) << 6)
|
||||
|
||||
/**
|
||||
* @name Transfer type.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_TTYPE_M2M (0 << 11)
|
||||
#define DMA_CFG_TTYPE_M2P (1UL << 11)
|
||||
#define DMA_CFG_TTYPE_P2M (2UL << 11)
|
||||
#define DMA_CFG_TTYPE_P2P (3UL << 11)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Interrupt error mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_IE (1UL << 14)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Terminal count interrupt mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ITC (1UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Active.
|
||||
* @note Read only
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ACTIVE (1UL << 17)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Halt.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_HALT (1UL << 18)
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_DMA_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
volatile uint32_t config; /**< @brief Configuration. */
|
||||
} lpc17xx_dma_channel_config_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
} lpc17xx_dma_lli_config_t;
|
||||
|
||||
/**
|
||||
* @brief DMA channel number.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_CHANNEL0 = 0,
|
||||
DMA_CHANNEL1 = 1,
|
||||
DMA_CHANNEL2 = 2,
|
||||
DMA_CHANNEL3 = 3,
|
||||
DMA_CHANNEL4 = 4,
|
||||
DMA_CHANNEL5 = 5,
|
||||
DMA_CHANNEL6 = 6,
|
||||
DMA_CHANNEL7 = 7
|
||||
|
||||
} lpc17xx_dma_channel_t;
|
||||
|
||||
/**
|
||||
* @brief DMA source or destination type.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_SSP0_TX = 0,
|
||||
DMA_SSP0_RX = 1,
|
||||
DMA_SSP1_TX = 2,
|
||||
DMA_SSP1_RX = 3,
|
||||
DMA_ADC = 4,
|
||||
DMA_I2S_CH0 = 5,
|
||||
DMA_I2S_CH1 = 6,
|
||||
DMA_DAC = 7,
|
||||
DMA_UART0_TX_MAT0_0 = 8,
|
||||
DMA_UART0_RX_MAT0_1 = 9,
|
||||
DMA_UART1_TX_MAT1_0 = 10,
|
||||
DMA_UART1_RX_MAT1_1 = 11,
|
||||
DMA_UART2_TX_MAT2_0 = 12,
|
||||
DMA_UART2_RX_MAT2_1 = 13,
|
||||
DMA_UART3_TX_MAT3_0 = 14,
|
||||
DMA_UART3_RX_MAT3_1 = 15
|
||||
} lpc17xx_dma_src_dst_t;
|
||||
|
||||
/**
|
||||
* @brief LPC17xx DMA ISR function type.
|
||||
*
|
||||
* @param[in] p parameter for the registered function
|
||||
* @param[in] flags pre-shifted content of the xISR register, the bits
|
||||
* are aligned to bit zero
|
||||
*/
|
||||
typedef void (*lpc17xx_dmaisr_t)(void *p, uint32_t flags);
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Macro Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Associates a memory source to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a source address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelSrcAddr(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CSrcAddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory destination to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a destination address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDstAddr(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CDestAddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a linked list item address to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a linked list item
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelLinkedList(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CLLI = ((uint32_t)(addr))
|
||||
|
||||
/**
|
||||
* @brief Set control configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] ctrl control configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelControl(dmach, ctrl) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CControl = (ctrl)
|
||||
|
||||
/**
|
||||
* @brief Set configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAllocate().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] config dma channel configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelConfig(dmach, config) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig = (config)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software burst transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftBurstRequest(src) \
|
||||
LPC_GPDMA->SoftBReq = (src)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software single transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftSingleRequest(src) \
|
||||
LPC_GPDMA->SoftSReq = (src)
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelEnable(dmach) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig |= (DMA_CFG_CH_ENABLE)
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDisable(dmach) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig &= ~(DMA_CFG_CH_ENABLE)
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern LPC_GPDMACH_TypeDef * _lpc17xx_dma_channel_config_t[];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dmaInit(void);
|
||||
bool_t dmaChannelAllocate(lpc17xx_dma_channel_t dmach,
|
||||
lpc17xx_dmaisr_t func,
|
||||
void *param);
|
||||
void dmaChannelRelease(lpc17xx_dma_channel_t dmach);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LPC17xx_DMA_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/LPC17xx_dma.h
|
||||
* @brief DMA driver header.
|
||||
*
|
||||
* @addtogroup LPC17xx_DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LPC17xx_DMA_H_
|
||||
#define _LPC17xx_DMA_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DMACCONFIG_E (1UL << 0)
|
||||
#define DMACCONFIG_M (1UL << 1)
|
||||
|
||||
/**
|
||||
* @brief Total number of DMA streams.
|
||||
* @note This is the total number of streams among all the DMA units.
|
||||
*/
|
||||
#define LPC17xx_DMA_CHANNELS 8
|
||||
|
||||
/**
|
||||
* @name DMA control data configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA transfer size.
|
||||
*
|
||||
* @param[in] n DMA transfer size
|
||||
*/
|
||||
#define DMA_CTRL_TRANSFER_SIZE(n) (n)
|
||||
|
||||
/**
|
||||
* @brief DMA source burst size.
|
||||
*/
|
||||
#define DMA_CTRL_SRC_BSIZE_1 (0 << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_4 (1UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_8 (2UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_16 (3UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_32 (4UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_64 (5UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_128 (6UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_256 (7UL << 12)
|
||||
|
||||
/**
|
||||
* @brief DMA destination burst size.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_BSIZE_1 (0 << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_4 (1UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_8 (2UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_16 (3UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_32 (4UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_64 (5UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_128 (6UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_256 (7UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_WIDTH_BYTE (0 << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_HWORD (1UL << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_WORD (2UL << 18)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_WIDTH_BYTE (0 << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_HWORD (1UL << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_WORD (2UL << 21)
|
||||
|
||||
/**
|
||||
* @name DMA source increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_NOINC (0UL << 26)
|
||||
#define DMA_CTRL_SRC_INC (1UL << 26)
|
||||
|
||||
/**
|
||||
* @name DMA destination increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_NOINC (0UL << 27)
|
||||
#define DMA_CTRL_DST_INC (1UL << 27)
|
||||
|
||||
/**
|
||||
* @name DMA bus access bits.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_PROT1_USER (0 << 28)
|
||||
#define DMA_CTRL_PROT1_PRIV (1UL << 28)
|
||||
|
||||
#define DMA_CTRL_PROT2_NONBUFF (0 << 29)
|
||||
#define DMA_CTRL_PROT2_BUFF (1UL << 29)
|
||||
|
||||
#define DMA_CTRL_PROT3_NONCACHE (0 << 30)
|
||||
#define DMA_CTRL_PROT3_CACHE (1UL << 30)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA terminal count interrupt enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_INT (1UL << 31)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA channel enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_CH_ENABLE (1UL << 0)
|
||||
|
||||
/**
|
||||
* @brief Source peripheral.
|
||||
*
|
||||
* @param[in] source source peripheral
|
||||
*/
|
||||
#define DMA_CFG_SRC_PERIPH(src) ((src) << 1)
|
||||
|
||||
/**
|
||||
* @brief Destination peripheral.
|
||||
*
|
||||
* @param[in] destination destination peripheral
|
||||
*/
|
||||
#define DMA_CFG_DST_PERIPH(dst) ((dst) << 6)
|
||||
|
||||
/**
|
||||
* @name Transfer type.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_TTYPE_M2M (0 << 11)
|
||||
#define DMA_CFG_TTYPE_M2P (1UL << 11)
|
||||
#define DMA_CFG_TTYPE_P2M (2UL << 11)
|
||||
#define DMA_CFG_TTYPE_P2P (3UL << 11)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Interrupt error mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_IE (1UL << 14)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Terminal count interrupt mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ITC (1UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Active.
|
||||
* @note Read only
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ACTIVE (1UL << 17)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Halt.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_HALT (1UL << 18)
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_DMA_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
volatile uint32_t config; /**< @brief Configuration. */
|
||||
} lpc17xx_dma_channel_config_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
} lpc17xx_dma_lli_config_t;
|
||||
|
||||
/**
|
||||
* @brief DMA channel number.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_CHANNEL0 = 0,
|
||||
DMA_CHANNEL1 = 1,
|
||||
DMA_CHANNEL2 = 2,
|
||||
DMA_CHANNEL3 = 3,
|
||||
DMA_CHANNEL4 = 4,
|
||||
DMA_CHANNEL5 = 5,
|
||||
DMA_CHANNEL6 = 6,
|
||||
DMA_CHANNEL7 = 7
|
||||
|
||||
} lpc17xx_dma_channel_t;
|
||||
|
||||
/**
|
||||
* @brief DMA source or destination type.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_SSP0_TX = 0,
|
||||
DMA_SSP0_RX = 1,
|
||||
DMA_SSP1_TX = 2,
|
||||
DMA_SSP1_RX = 3,
|
||||
DMA_ADC = 4,
|
||||
DMA_I2S_CH0 = 5,
|
||||
DMA_I2S_CH1 = 6,
|
||||
DMA_DAC = 7,
|
||||
DMA_UART0_TX_MAT0_0 = 8,
|
||||
DMA_UART0_RX_MAT0_1 = 9,
|
||||
DMA_UART1_TX_MAT1_0 = 10,
|
||||
DMA_UART1_RX_MAT1_1 = 11,
|
||||
DMA_UART2_TX_MAT2_0 = 12,
|
||||
DMA_UART2_RX_MAT2_1 = 13,
|
||||
DMA_UART3_TX_MAT3_0 = 14,
|
||||
DMA_UART3_RX_MAT3_1 = 15
|
||||
} lpc17xx_dma_src_dst_t;
|
||||
|
||||
/**
|
||||
* @brief LPC17xx DMA ISR function type.
|
||||
*
|
||||
* @param[in] p parameter for the registered function
|
||||
* @param[in] flags pre-shifted content of the xISR register, the bits
|
||||
* are aligned to bit zero
|
||||
*/
|
||||
typedef void (*lpc17xx_dmaisr_t)(void *p, uint32_t flags);
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Macro Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Associates a memory source to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a source address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelSrcAddr(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CSrcAddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory destination to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a destination address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDstAddr(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CDestAddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a linked list item address to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a linked list item
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelLinkedList(dmach, addr) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CLLI = ((uint32_t)(addr))
|
||||
|
||||
/**
|
||||
* @brief Set control configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] ctrl control configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelControl(dmach, ctrl) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CControl = (ctrl)
|
||||
|
||||
/**
|
||||
* @brief Set configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAllocate().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] config dma channel configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelConfig(dmach, config) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig = (config)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software burst transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftBurstRequest(src) \
|
||||
LPC_GPDMA->SoftBReq = (src)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software single transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftSingleRequest(src) \
|
||||
LPC_GPDMA->SoftSReq = (src)
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelEnable(dmach) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig |= (DMA_CFG_CH_ENABLE)
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDisable(dmach) \
|
||||
_lpc17xx_dma_channel_config_t[dmach]->CConfig &= ~(DMA_CFG_CH_ENABLE)
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern LPC_GPDMACH_TypeDef * _lpc17xx_dma_channel_config_t[];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dmaInit(void);
|
||||
bool_t dmaChannelAllocate(lpc17xx_dma_channel_t dmach,
|
||||
lpc17xx_dmaisr_t func,
|
||||
void *param);
|
||||
void dmaChannelRelease(lpc17xx_dma_channel_t dmach);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LPC17xx_DMA_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,158 +1,158 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/pal_lld.c
|
||||
* @brief LPC17xx GPIO low level driver code.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief LPC17xx I/O ports configuration.
|
||||
* @details GPIO unit registers initialization.
|
||||
*
|
||||
* @param[in] config the LPC17xx ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_init(const PALConfig *config) {
|
||||
|
||||
LPC_GPIO0->FIODIR = config->P0.dir;
|
||||
LPC_GPIO1->FIODIR = config->P1.dir;
|
||||
LPC_GPIO2->FIODIR = config->P2.dir;
|
||||
LPC_GPIO3->FIODIR = config->P3.dir;
|
||||
LPC_GPIO4->FIODIR = config->P4.dir;
|
||||
LPC_GPIO0->FIOMASK = 0;
|
||||
LPC_GPIO1->FIOMASK = 0;
|
||||
LPC_GPIO2->FIOMASK = 0;
|
||||
LPC_GPIO3->FIOMASK = 0;
|
||||
LPC_GPIO4->FIOMASK = 0;
|
||||
LPC_GPIO0->FIOPIN = config->P0.data;
|
||||
LPC_GPIO1->FIOPIN = config->P1.data;
|
||||
LPC_GPIO2->FIOPIN = config->P2.data;
|
||||
LPC_GPIO3->FIOPIN = config->P3.data;
|
||||
LPC_GPIO4->FIOPIN = config->P4.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset) {
|
||||
|
||||
uint32_t p;
|
||||
|
||||
port->FIOMASK = ~((mask) << offset);
|
||||
p = port->FIOPIN;
|
||||
port->FIOMASK = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits) {
|
||||
|
||||
port->FIOMASK = ~((mask) << offset);
|
||||
port->FIOPIN = bits;
|
||||
port->FIOMASK = 0;
|
||||
}
|
||||
/**
|
||||
* @brief Pads mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with
|
||||
* high state.
|
||||
* @note This function does not alter the @p PINSELx registers. Alternate
|
||||
* functions setup must be handled by device-specific code.
|
||||
*
|
||||
* @param[in] port the port identifier
|
||||
* @param[in] mask the group mask
|
||||
* @param[in] mode the mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode) {
|
||||
|
||||
switch (mode) {
|
||||
case PAL_MODE_RESET:
|
||||
case PAL_MODE_INPUT:
|
||||
port->FIODIR &= ~mask;
|
||||
break;
|
||||
case PAL_MODE_UNCONNECTED:
|
||||
palSetPort(port, PAL_WHOLE_PORT);
|
||||
case PAL_MODE_OUTPUT_PUSHPULL:
|
||||
port->FIODIR |= mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/pal_lld.c
|
||||
* @brief LPC17xx GPIO low level driver code.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief LPC17xx I/O ports configuration.
|
||||
* @details GPIO unit registers initialization.
|
||||
*
|
||||
* @param[in] config the LPC17xx ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_init(const PALConfig *config) {
|
||||
|
||||
LPC_GPIO0->FIODIR = config->P0.dir;
|
||||
LPC_GPIO1->FIODIR = config->P1.dir;
|
||||
LPC_GPIO2->FIODIR = config->P2.dir;
|
||||
LPC_GPIO3->FIODIR = config->P3.dir;
|
||||
LPC_GPIO4->FIODIR = config->P4.dir;
|
||||
LPC_GPIO0->FIOMASK = 0;
|
||||
LPC_GPIO1->FIOMASK = 0;
|
||||
LPC_GPIO2->FIOMASK = 0;
|
||||
LPC_GPIO3->FIOMASK = 0;
|
||||
LPC_GPIO4->FIOMASK = 0;
|
||||
LPC_GPIO0->FIOPIN = config->P0.data;
|
||||
LPC_GPIO1->FIOPIN = config->P1.data;
|
||||
LPC_GPIO2->FIOPIN = config->P2.data;
|
||||
LPC_GPIO3->FIOPIN = config->P3.data;
|
||||
LPC_GPIO4->FIOPIN = config->P4.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset) {
|
||||
|
||||
uint32_t p;
|
||||
|
||||
port->FIOMASK = ~((mask) << offset);
|
||||
p = port->FIOPIN;
|
||||
port->FIOMASK = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits) {
|
||||
|
||||
port->FIOMASK = ~((mask) << offset);
|
||||
port->FIOPIN = bits;
|
||||
port->FIOMASK = 0;
|
||||
}
|
||||
/**
|
||||
* @brief Pads mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with
|
||||
* high state.
|
||||
* @note This function does not alter the @p PINSELx registers. Alternate
|
||||
* functions setup must be handled by device-specific code.
|
||||
*
|
||||
* @param[in] port the port identifier
|
||||
* @param[in] mask the group mask
|
||||
* @param[in] mode the mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode) {
|
||||
|
||||
switch (mode) {
|
||||
case PAL_MODE_RESET:
|
||||
case PAL_MODE_INPUT:
|
||||
port->FIODIR &= ~mask;
|
||||
break;
|
||||
case PAL_MODE_UNCONNECTED:
|
||||
palSetPort(port, PAL_WHOLE_PORT);
|
||||
case PAL_MODE_OUTPUT_PUSHPULL:
|
||||
port->FIODIR |= mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,332 +1,332 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/pal_lld.h
|
||||
* @brief LPC17xx GPIO low level driver header.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _PAL_LLD_H_
|
||||
#define _PAL_LLD_H_
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Unsupported modes and specific modes */
|
||||
/*===========================================================================*/
|
||||
|
||||
#undef PAL_MODE_INPUT_PULLUP
|
||||
#undef PAL_MODE_INPUT_PULLDOWN
|
||||
#undef PAL_MODE_INPUT_ANALOG
|
||||
#undef PAL_MODE_OUTPUT_OPENDRAIN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Types and constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO port setup info.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Initial value for FIO_PIN register.*/
|
||||
uint32_t data;
|
||||
/** Initial value for FIO_DIR register.*/
|
||||
uint32_t dir;
|
||||
} lpc17xx_gpio_setup_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO static initializer.
|
||||
* @details An instance of this structure must be passed to @p palInit() at
|
||||
* system startup time in order to initialized the digital I/O
|
||||
* subsystem. This represents only the initial setup, specific pads
|
||||
* or whole ports can be reprogrammed at later time.
|
||||
* @note The @p IOCON block is not configured, initially all pins have
|
||||
* enabled pullups and are programmed as GPIO. It is responsibility
|
||||
* of the various drivers to reprogram the pins in the proper mode.
|
||||
* Pins that are not handled by any driver may be programmed in
|
||||
* @p board.c.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief GPIO 0 setup data.*/
|
||||
lpc17xx_gpio_setup_t P0;
|
||||
/** @brief GPIO 1 setup data.*/
|
||||
lpc17xx_gpio_setup_t P1;
|
||||
/** @brief GPIO 2 setup data.*/
|
||||
lpc17xx_gpio_setup_t P2;
|
||||
/** @brief GPIO 3 setup data.*/
|
||||
lpc17xx_gpio_setup_t P3;
|
||||
/** @brief GPIO 4 setup data.*/
|
||||
lpc17xx_gpio_setup_t P4;
|
||||
} PALConfig;
|
||||
|
||||
/**
|
||||
* @brief Width, in bits, of an I/O port.
|
||||
*/
|
||||
#define PAL_IOPORTS_WIDTH 32
|
||||
|
||||
/**
|
||||
* @brief Whole port mask.
|
||||
* @brief This macro specifies all the valid bits into a port.
|
||||
*/
|
||||
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* @brief Digital I/O port sized unsigned type.
|
||||
*/
|
||||
typedef uint32_t ioportmask_t;
|
||||
|
||||
/**
|
||||
* @brief Digital I/O modes.
|
||||
*/
|
||||
typedef uint32_t iomode_t;
|
||||
|
||||
/**
|
||||
* @brief Port Identifier.
|
||||
*/
|
||||
typedef LPC_GPIO_TypeDef *ioportid_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Identifiers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO0 port identifier.
|
||||
*/
|
||||
#define IOPORT1 LPC_GPIO0
|
||||
#define GPIO0 LPC_GPIO0
|
||||
|
||||
/**
|
||||
* @brief GPIO1 port identifier.
|
||||
*/
|
||||
#define IOPORT2 LPC_GPIO1
|
||||
#define GPIO1 LPC_GPIO1
|
||||
|
||||
/**
|
||||
* @brief GPIO2 port identifier.
|
||||
*/
|
||||
#define IOPORT3 LPC_GPIO2
|
||||
#define GPIO2 LPC_GPIO2
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT4 LPC_GPIO3
|
||||
#define GPIO3 LPC_GPIO3
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT5 LPC_GPIO4
|
||||
#define GPIO4 LPC_GPIO4
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Implementation, some of the following macros could be implemented as */
|
||||
/* functions, if so please put them in pal_lld.c. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level PAL subsystem initialization.
|
||||
*
|
||||
* @param[in] config architecture-dependent ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_init(config) _pal_lld_init(config)
|
||||
|
||||
/**
|
||||
* @brief Reads the physical I/O port states.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The port bits.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readport(port) ((port)->FIOPIN)
|
||||
|
||||
/**
|
||||
* @brief Reads the output latch.
|
||||
* @details The purpose of this function is to read back the latched output
|
||||
* value.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The latched logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readlatch(port) ((port)->FIOPIN)
|
||||
|
||||
/**
|
||||
* @brief Writes a bits mask on a I/O port.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be written on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writeport(port, bits) ((port)->FIOPIN = (bits))
|
||||
|
||||
/**
|
||||
* @brief Sets a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be ORed on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setport(port, bits) ((port)->FIOSET = bits)
|
||||
|
||||
/**
|
||||
* @brief Clears a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be cleared on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearport(port, bits) ((port)->FIOCLR = bits)
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readgroup(port, mask, offset) \
|
||||
_pal_lld_readgroup(port, mask, offset)
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writegroup(port, mask, offset, bits) \
|
||||
_pal_lld_writegroup(port, mask, offset, bits)
|
||||
|
||||
/**
|
||||
* @brief Pads group mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note Programming an unknown or unsupported mode is silently ignored.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] mode group mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setgroupmode(port, mask, offset, mode) \
|
||||
_pal_lld_setgroupmode(port, mask << offset, mode)
|
||||
|
||||
/**
|
||||
* @brief Writes a logical state on an output pad.
|
||||
* @note This function is not meant to be invoked directly by the
|
||||
* application code.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
* @param[in] bit logical value, the value must be @p PAL_LOW or
|
||||
* @p PAL_HIGH
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writepad(port, pad, bit) \
|
||||
((bit) == PAL_LOW) ? pal_lld_clearpad(port, pad) : \
|
||||
pal_lld_setpad(port, pad)
|
||||
|
||||
/**
|
||||
* @brief Sets a pad logical state to @p PAL_HIGH.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setpad(port, pad) \
|
||||
((port)->FIOSET = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Clears a pad logical state to @p PAL_LOW.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearpad(port, pad) \
|
||||
((port)->FIOCLR = 1UL << (pad))
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern const PALConfig pal_default_config;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void _pal_lld_init(const PALConfig *config);
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset);
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits);
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
#endif /* _PAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/pal_lld.h
|
||||
* @brief LPC17xx GPIO low level driver header.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _PAL_LLD_H_
|
||||
#define _PAL_LLD_H_
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Unsupported modes and specific modes */
|
||||
/*===========================================================================*/
|
||||
|
||||
#undef PAL_MODE_INPUT_PULLUP
|
||||
#undef PAL_MODE_INPUT_PULLDOWN
|
||||
#undef PAL_MODE_INPUT_ANALOG
|
||||
#undef PAL_MODE_OUTPUT_OPENDRAIN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Types and constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO port setup info.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Initial value for FIO_PIN register.*/
|
||||
uint32_t data;
|
||||
/** Initial value for FIO_DIR register.*/
|
||||
uint32_t dir;
|
||||
} lpc17xx_gpio_setup_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO static initializer.
|
||||
* @details An instance of this structure must be passed to @p palInit() at
|
||||
* system startup time in order to initialized the digital I/O
|
||||
* subsystem. This represents only the initial setup, specific pads
|
||||
* or whole ports can be reprogrammed at later time.
|
||||
* @note The @p IOCON block is not configured, initially all pins have
|
||||
* enabled pullups and are programmed as GPIO. It is responsibility
|
||||
* of the various drivers to reprogram the pins in the proper mode.
|
||||
* Pins that are not handled by any driver may be programmed in
|
||||
* @p board.c.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief GPIO 0 setup data.*/
|
||||
lpc17xx_gpio_setup_t P0;
|
||||
/** @brief GPIO 1 setup data.*/
|
||||
lpc17xx_gpio_setup_t P1;
|
||||
/** @brief GPIO 2 setup data.*/
|
||||
lpc17xx_gpio_setup_t P2;
|
||||
/** @brief GPIO 3 setup data.*/
|
||||
lpc17xx_gpio_setup_t P3;
|
||||
/** @brief GPIO 4 setup data.*/
|
||||
lpc17xx_gpio_setup_t P4;
|
||||
} PALConfig;
|
||||
|
||||
/**
|
||||
* @brief Width, in bits, of an I/O port.
|
||||
*/
|
||||
#define PAL_IOPORTS_WIDTH 32
|
||||
|
||||
/**
|
||||
* @brief Whole port mask.
|
||||
* @brief This macro specifies all the valid bits into a port.
|
||||
*/
|
||||
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* @brief Digital I/O port sized unsigned type.
|
||||
*/
|
||||
typedef uint32_t ioportmask_t;
|
||||
|
||||
/**
|
||||
* @brief Digital I/O modes.
|
||||
*/
|
||||
typedef uint32_t iomode_t;
|
||||
|
||||
/**
|
||||
* @brief Port Identifier.
|
||||
*/
|
||||
typedef LPC_GPIO_TypeDef *ioportid_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Identifiers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO0 port identifier.
|
||||
*/
|
||||
#define IOPORT1 LPC_GPIO0
|
||||
#define GPIO0 LPC_GPIO0
|
||||
|
||||
/**
|
||||
* @brief GPIO1 port identifier.
|
||||
*/
|
||||
#define IOPORT2 LPC_GPIO1
|
||||
#define GPIO1 LPC_GPIO1
|
||||
|
||||
/**
|
||||
* @brief GPIO2 port identifier.
|
||||
*/
|
||||
#define IOPORT3 LPC_GPIO2
|
||||
#define GPIO2 LPC_GPIO2
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT4 LPC_GPIO3
|
||||
#define GPIO3 LPC_GPIO3
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT5 LPC_GPIO4
|
||||
#define GPIO4 LPC_GPIO4
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Implementation, some of the following macros could be implemented as */
|
||||
/* functions, if so please put them in pal_lld.c. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level PAL subsystem initialization.
|
||||
*
|
||||
* @param[in] config architecture-dependent ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_init(config) _pal_lld_init(config)
|
||||
|
||||
/**
|
||||
* @brief Reads the physical I/O port states.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The port bits.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readport(port) ((port)->FIOPIN)
|
||||
|
||||
/**
|
||||
* @brief Reads the output latch.
|
||||
* @details The purpose of this function is to read back the latched output
|
||||
* value.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The latched logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readlatch(port) ((port)->FIOPIN)
|
||||
|
||||
/**
|
||||
* @brief Writes a bits mask on a I/O port.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be written on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writeport(port, bits) ((port)->FIOPIN = (bits))
|
||||
|
||||
/**
|
||||
* @brief Sets a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be ORed on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setport(port, bits) ((port)->FIOSET = bits)
|
||||
|
||||
/**
|
||||
* @brief Clears a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be cleared on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearport(port, bits) ((port)->FIOCLR = bits)
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readgroup(port, mask, offset) \
|
||||
_pal_lld_readgroup(port, mask, offset)
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writegroup(port, mask, offset, bits) \
|
||||
_pal_lld_writegroup(port, mask, offset, bits)
|
||||
|
||||
/**
|
||||
* @brief Pads group mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note Programming an unknown or unsupported mode is silently ignored.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] mode group mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setgroupmode(port, mask, offset, mode) \
|
||||
_pal_lld_setgroupmode(port, mask << offset, mode)
|
||||
|
||||
/**
|
||||
* @brief Writes a logical state on an output pad.
|
||||
* @note This function is not meant to be invoked directly by the
|
||||
* application code.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
* @param[in] bit logical value, the value must be @p PAL_LOW or
|
||||
* @p PAL_HIGH
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writepad(port, pad, bit) \
|
||||
((bit) == PAL_LOW) ? pal_lld_clearpad(port, pad) : \
|
||||
pal_lld_setpad(port, pad)
|
||||
|
||||
/**
|
||||
* @brief Sets a pad logical state to @p PAL_HIGH.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setpad(port, pad) \
|
||||
((port)->FIOSET = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Clears a pad logical state to @p PAL_LOW.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearpad(port, pad) \
|
||||
((port)->FIOCLR = 1UL << (pad))
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern const PALConfig pal_default_config;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void _pal_lld_init(const PALConfig *config);
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset);
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits);
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
#endif /* _PAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
# List of all the LPC17xx platform files.
|
||||
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC17xx/hal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/lpc17xx_dma.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/adc_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/gpt_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/pal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/serial_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/rtc_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/i2c_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/spi_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/dac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/mac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/can_lld.c
|
||||
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC17xx
|
||||
# List of all the LPC17xx platform files.
|
||||
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC17xx/hal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/lpc17xx_dma.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/adc_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/gpt_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/pal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/serial_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/rtc_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/i2c_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/spi_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/dac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/mac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC17xx/can_lld.c
|
||||
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC17xx
|
||||
|
|
|
@ -1,290 +1,290 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx RTC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/rtc_lld.c
|
||||
* @brief LPC17xx RTC low level driver.
|
||||
*
|
||||
* @addtogroup RTC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief RTC driver identifier.
|
||||
*/
|
||||
RTCDriver RTCD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enable RTC clock.
|
||||
*/
|
||||
#define _rtc_clk_enable() \
|
||||
LPC_RTC->CCR |= CCR_CLKEN
|
||||
|
||||
/**
|
||||
* @brief Disable RTC clock.
|
||||
*/
|
||||
#define _rtc_clk_disable() \
|
||||
LPC_RTC->CCR &= ~CCR_CLKEN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief RTC interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
|
||||
#if LPC17xx_RTC_USE_ALARM || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector84) {
|
||||
uint32_t status;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
status = LPC_RTC->ILR;
|
||||
LPC_RTC->ILR = status; /* Clear interrupt flag */
|
||||
|
||||
if ((status & ILR_RTCALF) && (RTCD1.callback != NULL))
|
||||
RTCD1.callback(&RTCD1, RTC_EVENT_ALARM);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enable access to registers.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_init(void) {
|
||||
|
||||
if(LPC_RTC->RTC_AUX & RTC_AUX_RTC_OSCF) { /* Set after RTC power was first turn. */
|
||||
|
||||
LPC_RTC->CCR = CCR_CCALEN; /* Disable calibration and RTC clock. */
|
||||
LPC_RTC->CALIBRATION = 0;
|
||||
LPC_RTC->RTC_AUX = RTC_AUX_RTC_OSCF; /* Clear RTC Oscillator Fail detect flag. */
|
||||
|
||||
LPC_RTC->CIIR = 0; /* Disable Counter Increment Interrupt. */
|
||||
LPC_RTC->AMR = AMR_MASK_ALL; /* Mask alarm interrupt. */
|
||||
LPC_RTC->ILR = ILR_RTCALF | ILR_RTCCIF; /* Clear interrupt flags. */
|
||||
|
||||
/* Set date to Saturday 01.01.2000 00:00:00 */
|
||||
LPC_RTC->SEC = 0;
|
||||
LPC_RTC->MIN = 0;
|
||||
LPC_RTC->HOUR = 0;
|
||||
LPC_RTC->DOM = 1;
|
||||
LPC_RTC->MONTH = 1;
|
||||
LPC_RTC->YEAR = 2000;
|
||||
LPC_RTC->DOW = 6;
|
||||
LPC_RTC->DOY = 1;
|
||||
|
||||
_rtc_clk_enable(); /* Enable RTC clock. */
|
||||
}
|
||||
|
||||
#if LPC17xx_RTC_USE_ALARM
|
||||
nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_RTC_IRQ_PRIORITY));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set current time.
|
||||
* @note Fractional part will be silently ignored. There is no possibility
|
||||
* to set it on STM32 platform.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) {
|
||||
(void)rtcp;
|
||||
|
||||
_rtc_clk_disable(); /* Disable RTC clock. */
|
||||
LPC_RTC->SEC = timespec->sec;
|
||||
LPC_RTC->MIN = timespec->min;
|
||||
LPC_RTC->HOUR = timespec->hour;
|
||||
LPC_RTC->DOM = timespec->dom;
|
||||
LPC_RTC->MONTH = timespec->month;
|
||||
LPC_RTC->YEAR = timespec->year;
|
||||
LPC_RTC->DOW = timespec->dow;
|
||||
LPC_RTC->DOY = timespec->doy;
|
||||
_rtc_clk_enable(); /* Enable RTC clock. */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) {
|
||||
(void)rtcp;
|
||||
|
||||
timespec->sec = LPC_RTC->SEC;
|
||||
timespec->min = LPC_RTC->MIN;
|
||||
timespec->hour = LPC_RTC->HOUR;
|
||||
timespec->dom = LPC_RTC->DOM;
|
||||
timespec->month = LPC_RTC->MONTH;
|
||||
timespec->year = LPC_RTC->YEAR;
|
||||
timespec->dow = LPC_RTC->DOW;
|
||||
timespec->doy = LPC_RTC->DOY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set alarm time.
|
||||
*
|
||||
* @note Default value after BKP domain reset for both comparators is 0.
|
||||
* @note Function does not performs any checks of alarm time validity.
|
||||
*
|
||||
* @param[in] rtcp Pointer to RTC driver structure.
|
||||
* @param[in] alarm Alarm identifier. Can be 1 or 2.
|
||||
* @param[in] alarmspec Pointer to a @p RTCAlarm structure.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
const RTCAlarm *alarmspec) {
|
||||
(void)rtcp;
|
||||
(void)alarm;
|
||||
LPC_RTC->ALSEC = alarmspec->alsec;
|
||||
LPC_RTC->ALMIN = alarmspec->almin;
|
||||
LPC_RTC->ALHOUR = alarmspec->alhour;
|
||||
LPC_RTC->ALDOM = alarmspec->aldom;
|
||||
LPC_RTC->ALMON = alarmspec->almonth;
|
||||
LPC_RTC->ALYEAR = alarmspec->alyear;
|
||||
LPC_RTC->ALDOW = alarmspec->aldow;
|
||||
LPC_RTC->ALDOY = alarmspec->aldoy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get alarm time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] alarm alarm identifier
|
||||
* @param[out] alarmspec pointer to a @p RTCAlarm structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_get_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
RTCAlarm *alarmspec) {
|
||||
(void)rtcp;
|
||||
(void)alarm;
|
||||
alarmspec->alsec = LPC_RTC->ALSEC;
|
||||
alarmspec->almin = LPC_RTC->ALMIN;
|
||||
alarmspec->alhour = LPC_RTC->ALHOUR;
|
||||
alarmspec->aldom = LPC_RTC->ALDOM;
|
||||
alarmspec->almonth = LPC_RTC->ALMON;
|
||||
alarmspec->alyear = LPC_RTC->ALYEAR;
|
||||
alarmspec->aldow = LPC_RTC->ALDOW;
|
||||
alarmspec->aldoy = LPC_RTC->ALDOY;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables RTC callbacks.
|
||||
* @details This function enables or disables callbacks, use a @p NULL pointer
|
||||
* in order to disable a callback.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] callback callback function pointer or @p NULL
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
|
||||
|
||||
LPC_RTC->AMR = AMR_MASK_ALL; /* Mask alarm interrupt. */
|
||||
LPC_RTC->ILR = ILR_RTCALF; /* Clear interrupt flag. */
|
||||
|
||||
if (callback != NULL) {
|
||||
|
||||
/* IRQ sources enabled only after setting up the callback.*/
|
||||
rtcp->callback = callback;
|
||||
LPC_RTC->AMR = 0; /* Enable alarm interrupt. */
|
||||
}
|
||||
else {
|
||||
|
||||
/* Callback set to NULL only after disabling the IRQ sources.*/
|
||||
rtcp->callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#include "chrtclib.h"
|
||||
|
||||
/**
|
||||
* @brief Get current time in format suitable for usage in FatFS.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return FAT time value.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) {
|
||||
uint32_t fattime;
|
||||
struct tm timp;
|
||||
|
||||
rtcGetTimeTm(rtcp, &timp);
|
||||
|
||||
fattime = (timp.tm_sec) >> 1;
|
||||
fattime |= (timp.tm_min) << 5;
|
||||
fattime |= (timp.tm_hour) << 11;
|
||||
fattime |= (timp.tm_mday) << 16;
|
||||
fattime |= (timp.tm_mon + 1) << 21;
|
||||
fattime |= (timp.tm_year - 80) << 25;
|
||||
|
||||
return fattime;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx RTC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/rtc_lld.c
|
||||
* @brief LPC17xx RTC low level driver.
|
||||
*
|
||||
* @addtogroup RTC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief RTC driver identifier.
|
||||
*/
|
||||
RTCDriver RTCD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enable RTC clock.
|
||||
*/
|
||||
#define _rtc_clk_enable() \
|
||||
LPC_RTC->CCR |= CCR_CLKEN
|
||||
|
||||
/**
|
||||
* @brief Disable RTC clock.
|
||||
*/
|
||||
#define _rtc_clk_disable() \
|
||||
LPC_RTC->CCR &= ~CCR_CLKEN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief RTC interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
|
||||
#if LPC17xx_RTC_USE_ALARM || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector84) {
|
||||
uint32_t status;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
status = LPC_RTC->ILR;
|
||||
LPC_RTC->ILR = status; /* Clear interrupt flag */
|
||||
|
||||
if ((status & ILR_RTCALF) && (RTCD1.callback != NULL))
|
||||
RTCD1.callback(&RTCD1, RTC_EVENT_ALARM);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enable access to registers.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_init(void) {
|
||||
|
||||
if(LPC_RTC->RTC_AUX & RTC_AUX_RTC_OSCF) { /* Set after RTC power was first turn. */
|
||||
|
||||
LPC_RTC->CCR = CCR_CCALEN; /* Disable calibration and RTC clock. */
|
||||
LPC_RTC->CALIBRATION = 0;
|
||||
LPC_RTC->RTC_AUX = RTC_AUX_RTC_OSCF; /* Clear RTC Oscillator Fail detect flag. */
|
||||
|
||||
LPC_RTC->CIIR = 0; /* Disable Counter Increment Interrupt. */
|
||||
LPC_RTC->AMR = AMR_MASK_ALL; /* Mask alarm interrupt. */
|
||||
LPC_RTC->ILR = ILR_RTCALF | ILR_RTCCIF; /* Clear interrupt flags. */
|
||||
|
||||
/* Set date to Saturday 01.01.2000 00:00:00 */
|
||||
LPC_RTC->SEC = 0;
|
||||
LPC_RTC->MIN = 0;
|
||||
LPC_RTC->HOUR = 0;
|
||||
LPC_RTC->DOM = 1;
|
||||
LPC_RTC->MONTH = 1;
|
||||
LPC_RTC->YEAR = 2000;
|
||||
LPC_RTC->DOW = 6;
|
||||
LPC_RTC->DOY = 1;
|
||||
|
||||
_rtc_clk_enable(); /* Enable RTC clock. */
|
||||
}
|
||||
|
||||
#if LPC17xx_RTC_USE_ALARM
|
||||
nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(LPC17xx_RTC_IRQ_PRIORITY));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set current time.
|
||||
* @note Fractional part will be silently ignored. There is no possibility
|
||||
* to set it on STM32 platform.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec) {
|
||||
(void)rtcp;
|
||||
|
||||
_rtc_clk_disable(); /* Disable RTC clock. */
|
||||
LPC_RTC->SEC = timespec->sec;
|
||||
LPC_RTC->MIN = timespec->min;
|
||||
LPC_RTC->HOUR = timespec->hour;
|
||||
LPC_RTC->DOM = timespec->dom;
|
||||
LPC_RTC->MONTH = timespec->month;
|
||||
LPC_RTC->YEAR = timespec->year;
|
||||
LPC_RTC->DOW = timespec->dow;
|
||||
LPC_RTC->DOY = timespec->doy;
|
||||
_rtc_clk_enable(); /* Enable RTC clock. */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[out] timespec pointer to a @p RTCTime structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec) {
|
||||
(void)rtcp;
|
||||
|
||||
timespec->sec = LPC_RTC->SEC;
|
||||
timespec->min = LPC_RTC->MIN;
|
||||
timespec->hour = LPC_RTC->HOUR;
|
||||
timespec->dom = LPC_RTC->DOM;
|
||||
timespec->month = LPC_RTC->MONTH;
|
||||
timespec->year = LPC_RTC->YEAR;
|
||||
timespec->dow = LPC_RTC->DOW;
|
||||
timespec->doy = LPC_RTC->DOY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set alarm time.
|
||||
*
|
||||
* @note Default value after BKP domain reset for both comparators is 0.
|
||||
* @note Function does not performs any checks of alarm time validity.
|
||||
*
|
||||
* @param[in] rtcp Pointer to RTC driver structure.
|
||||
* @param[in] alarm Alarm identifier. Can be 1 or 2.
|
||||
* @param[in] alarmspec Pointer to a @p RTCAlarm structure.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
const RTCAlarm *alarmspec) {
|
||||
(void)rtcp;
|
||||
(void)alarm;
|
||||
LPC_RTC->ALSEC = alarmspec->alsec;
|
||||
LPC_RTC->ALMIN = alarmspec->almin;
|
||||
LPC_RTC->ALHOUR = alarmspec->alhour;
|
||||
LPC_RTC->ALDOM = alarmspec->aldom;
|
||||
LPC_RTC->ALMON = alarmspec->almonth;
|
||||
LPC_RTC->ALYEAR = alarmspec->alyear;
|
||||
LPC_RTC->ALDOW = alarmspec->aldow;
|
||||
LPC_RTC->ALDOY = alarmspec->aldoy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get alarm time.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] alarm alarm identifier
|
||||
* @param[out] alarmspec pointer to a @p RTCAlarm structure
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void rtc_lld_get_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
RTCAlarm *alarmspec) {
|
||||
(void)rtcp;
|
||||
(void)alarm;
|
||||
alarmspec->alsec = LPC_RTC->ALSEC;
|
||||
alarmspec->almin = LPC_RTC->ALMIN;
|
||||
alarmspec->alhour = LPC_RTC->ALHOUR;
|
||||
alarmspec->aldom = LPC_RTC->ALDOM;
|
||||
alarmspec->almonth = LPC_RTC->ALMON;
|
||||
alarmspec->alyear = LPC_RTC->ALYEAR;
|
||||
alarmspec->aldow = LPC_RTC->ALDOW;
|
||||
alarmspec->aldoy = LPC_RTC->ALDOY;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables RTC callbacks.
|
||||
* @details This function enables or disables callbacks, use a @p NULL pointer
|
||||
* in order to disable a callback.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @param[in] callback callback function pointer or @p NULL
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
|
||||
|
||||
LPC_RTC->AMR = AMR_MASK_ALL; /* Mask alarm interrupt. */
|
||||
LPC_RTC->ILR = ILR_RTCALF; /* Clear interrupt flag. */
|
||||
|
||||
if (callback != NULL) {
|
||||
|
||||
/* IRQ sources enabled only after setting up the callback.*/
|
||||
rtcp->callback = callback;
|
||||
LPC_RTC->AMR = 0; /* Enable alarm interrupt. */
|
||||
}
|
||||
else {
|
||||
|
||||
/* Callback set to NULL only after disabling the IRQ sources.*/
|
||||
rtcp->callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#include "chrtclib.h"
|
||||
|
||||
/**
|
||||
* @brief Get current time in format suitable for usage in FatFS.
|
||||
*
|
||||
* @param[in] rtcp pointer to RTC driver structure
|
||||
* @return FAT time value.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp) {
|
||||
uint32_t fattime;
|
||||
struct tm timp;
|
||||
|
||||
rtcGetTimeTm(rtcp, &timp);
|
||||
|
||||
fattime = (timp.tm_sec) >> 1;
|
||||
fattime |= (timp.tm_min) << 5;
|
||||
fattime |= (timp.tm_hour) << 11;
|
||||
fattime |= (timp.tm_mday) << 16;
|
||||
fattime |= (timp.tm_mon + 1) << 21;
|
||||
fattime |= (timp.tm_year - 80) << 25;
|
||||
|
||||
return fattime;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,279 +1,279 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx RTC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/rtc_lld.h
|
||||
* @brief LPC17xx RTC low level driver header.
|
||||
*
|
||||
* @addtogroup RTC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _RTC_LLD_H_
|
||||
#define _RTC_LLD_H_
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define ILR_RTCCIF 0x01
|
||||
#define ILR_RTCALF 0x02
|
||||
|
||||
#define CCR_CLKEN 0x01
|
||||
#define CCR_CTCRST 0x02
|
||||
#define CCR_CCALEN 0x10
|
||||
|
||||
#define CIIR_IMSEC 0x01
|
||||
#define CIIR_IMMIN 0x02
|
||||
#define CIIR_IMHOUR 0x04
|
||||
#define CIIR_IMDOM 0x08
|
||||
#define CIIR_IMDOW 0x10
|
||||
#define CIIR_IMDOY 0x20
|
||||
#define CIIR_IMMON 0x40
|
||||
#define CIIR_IMYEAR 0x80
|
||||
|
||||
#define AMR_AMRSEC 0x01
|
||||
#define AMR_AMRMIN 0x02
|
||||
#define AMR_AMRHOUR 0x04
|
||||
#define AMR_AMRDOM 0x08
|
||||
#define AMR_AMRDOW 0x10
|
||||
#define AMR_AMRDOY 0x20
|
||||
#define AMR_AMRMON 0x40
|
||||
#define AMR_AMRYEAR 0x80
|
||||
#define AMR_MASK_ALL 0xFF
|
||||
|
||||
#define RTC_AUX_RTC_OSCF 0x10
|
||||
|
||||
#define RTC_AUXEN_RTC_OSCFEN 0x10
|
||||
|
||||
/**
|
||||
* @brief This RTC implementation supports callbacks.
|
||||
*/
|
||||
#define RTC_SUPPORTS_CALLBACKS TRUE
|
||||
|
||||
/**
|
||||
* @brief One alarm comparator available.
|
||||
*/
|
||||
#define RTC_ALARMS 1
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTC Alarm enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_RTC_USE_ALARM) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_RTC_USE_ALARM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief RTC IRQ Priority.
|
||||
*/
|
||||
#if !defined(LPC17xx_RTC_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_RTC_IRQ_PRIORITY 3
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC alarm time stamp.
|
||||
*/
|
||||
typedef struct RTCAlarm RTCAlarm;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC wakeup period.
|
||||
*/
|
||||
typedef struct RTCWakeup RTCWakeup;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC callbacks config.
|
||||
*/
|
||||
typedef struct RTCCallbackConfig RTCCallbackConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of an RTC alarm.
|
||||
* @details Meaningful on platforms with more than 1 alarm comparator.
|
||||
*/
|
||||
typedef uint32_t rtcalarm_t;
|
||||
|
||||
/**
|
||||
* @brief Type of an RTC event.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_EVENT_ALARM = 0 /** Triggered on alarm. */
|
||||
} rtcevent_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a generic RTC callback.
|
||||
*/
|
||||
typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC callbacks config.
|
||||
*/
|
||||
struct RTCCallbackConfig{
|
||||
/**
|
||||
* @brief Generic RTC callback pointer.
|
||||
*/
|
||||
rtccb_t callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC time stamp.
|
||||
*/
|
||||
struct RTCTime {
|
||||
/**
|
||||
* @brief RTC seconds register.
|
||||
*/
|
||||
uint8_t sec;
|
||||
/**
|
||||
* @brief RTC minutes register.
|
||||
*/
|
||||
uint8_t min;
|
||||
/**
|
||||
* @brief RTC hours register.
|
||||
*/
|
||||
uint8_t hour;
|
||||
/**
|
||||
* @brief RTC day of month register.
|
||||
*/
|
||||
uint8_t dom;
|
||||
/**
|
||||
* @brief RTC month register.
|
||||
*/
|
||||
uint8_t month;
|
||||
/**
|
||||
* @brief RTC day of week register.
|
||||
*/
|
||||
uint8_t dow;
|
||||
/**
|
||||
* @brief RTC year register.
|
||||
*/
|
||||
uint16_t year;
|
||||
/**
|
||||
* @brief RTC day of year register.
|
||||
*/
|
||||
uint16_t doy;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC alarm time stamp.
|
||||
*/
|
||||
struct RTCAlarm {
|
||||
/**
|
||||
* @brief RTC alarm seconds register.
|
||||
*/
|
||||
uint8_t alsec;
|
||||
/**
|
||||
* @brief RTC alarm minutes register.
|
||||
*/
|
||||
uint8_t almin;
|
||||
/**
|
||||
* @brief RTC alarm hours register.
|
||||
*/
|
||||
uint8_t alhour;
|
||||
/**
|
||||
* @brief RTC alarm day of month register.
|
||||
*/
|
||||
uint8_t aldom;
|
||||
/**
|
||||
* @brief RTC alarm month register.
|
||||
*/
|
||||
uint8_t almonth;
|
||||
/**
|
||||
* @brief RTC alarm day of week register.
|
||||
*/
|
||||
uint8_t aldow;
|
||||
/**
|
||||
* @brief RTC alarm year register.
|
||||
*/
|
||||
uint16_t alyear;
|
||||
/**
|
||||
* @brief RTC alarm day of year register.
|
||||
*/
|
||||
uint16_t aldoy;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC driver.
|
||||
*/
|
||||
struct RTCDriver{
|
||||
/**
|
||||
* @brief Callback pointer.
|
||||
*/
|
||||
rtccb_t callback;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern RTCDriver RTCD1;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void rtc_lld_init(void);
|
||||
void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec);
|
||||
void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec);
|
||||
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
const RTCAlarm *alarmspec);
|
||||
void rtc_lld_get_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
RTCAlarm *alarmspec);
|
||||
void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
|
||||
uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
#endif /* _RTC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC17xx RTC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
/*
|
||||
Concepts and parts of this file have been contributed by Uladzimir Pylinsky
|
||||
aka barthess.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/rtc_lld.h
|
||||
* @brief LPC17xx RTC low level driver header.
|
||||
*
|
||||
* @addtogroup RTC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _RTC_LLD_H_
|
||||
#define _RTC_LLD_H_
|
||||
|
||||
#if HAL_USE_RTC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define ILR_RTCCIF 0x01
|
||||
#define ILR_RTCALF 0x02
|
||||
|
||||
#define CCR_CLKEN 0x01
|
||||
#define CCR_CTCRST 0x02
|
||||
#define CCR_CCALEN 0x10
|
||||
|
||||
#define CIIR_IMSEC 0x01
|
||||
#define CIIR_IMMIN 0x02
|
||||
#define CIIR_IMHOUR 0x04
|
||||
#define CIIR_IMDOM 0x08
|
||||
#define CIIR_IMDOW 0x10
|
||||
#define CIIR_IMDOY 0x20
|
||||
#define CIIR_IMMON 0x40
|
||||
#define CIIR_IMYEAR 0x80
|
||||
|
||||
#define AMR_AMRSEC 0x01
|
||||
#define AMR_AMRMIN 0x02
|
||||
#define AMR_AMRHOUR 0x04
|
||||
#define AMR_AMRDOM 0x08
|
||||
#define AMR_AMRDOW 0x10
|
||||
#define AMR_AMRDOY 0x20
|
||||
#define AMR_AMRMON 0x40
|
||||
#define AMR_AMRYEAR 0x80
|
||||
#define AMR_MASK_ALL 0xFF
|
||||
|
||||
#define RTC_AUX_RTC_OSCF 0x10
|
||||
|
||||
#define RTC_AUXEN_RTC_OSCFEN 0x10
|
||||
|
||||
/**
|
||||
* @brief This RTC implementation supports callbacks.
|
||||
*/
|
||||
#define RTC_SUPPORTS_CALLBACKS TRUE
|
||||
|
||||
/**
|
||||
* @brief One alarm comparator available.
|
||||
*/
|
||||
#define RTC_ALARMS 1
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief RTC Alarm enable.
|
||||
*/
|
||||
#if !defined(LPC17xx_RTC_USE_ALARM) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_RTC_USE_ALARM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief RTC IRQ Priority.
|
||||
*/
|
||||
#if !defined(LPC17xx_RTC_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_RTC_IRQ_PRIORITY 3
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC alarm time stamp.
|
||||
*/
|
||||
typedef struct RTCAlarm RTCAlarm;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC wakeup period.
|
||||
*/
|
||||
typedef struct RTCWakeup RTCWakeup;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an RTC callbacks config.
|
||||
*/
|
||||
typedef struct RTCCallbackConfig RTCCallbackConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of an RTC alarm.
|
||||
* @details Meaningful on platforms with more than 1 alarm comparator.
|
||||
*/
|
||||
typedef uint32_t rtcalarm_t;
|
||||
|
||||
/**
|
||||
* @brief Type of an RTC event.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_EVENT_ALARM = 0 /** Triggered on alarm. */
|
||||
} rtcevent_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a generic RTC callback.
|
||||
*/
|
||||
typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC callbacks config.
|
||||
*/
|
||||
struct RTCCallbackConfig{
|
||||
/**
|
||||
* @brief Generic RTC callback pointer.
|
||||
*/
|
||||
rtccb_t callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC time stamp.
|
||||
*/
|
||||
struct RTCTime {
|
||||
/**
|
||||
* @brief RTC seconds register.
|
||||
*/
|
||||
uint8_t sec;
|
||||
/**
|
||||
* @brief RTC minutes register.
|
||||
*/
|
||||
uint8_t min;
|
||||
/**
|
||||
* @brief RTC hours register.
|
||||
*/
|
||||
uint8_t hour;
|
||||
/**
|
||||
* @brief RTC day of month register.
|
||||
*/
|
||||
uint8_t dom;
|
||||
/**
|
||||
* @brief RTC month register.
|
||||
*/
|
||||
uint8_t month;
|
||||
/**
|
||||
* @brief RTC day of week register.
|
||||
*/
|
||||
uint8_t dow;
|
||||
/**
|
||||
* @brief RTC year register.
|
||||
*/
|
||||
uint16_t year;
|
||||
/**
|
||||
* @brief RTC day of year register.
|
||||
*/
|
||||
uint16_t doy;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC alarm time stamp.
|
||||
*/
|
||||
struct RTCAlarm {
|
||||
/**
|
||||
* @brief RTC alarm seconds register.
|
||||
*/
|
||||
uint8_t alsec;
|
||||
/**
|
||||
* @brief RTC alarm minutes register.
|
||||
*/
|
||||
uint8_t almin;
|
||||
/**
|
||||
* @brief RTC alarm hours register.
|
||||
*/
|
||||
uint8_t alhour;
|
||||
/**
|
||||
* @brief RTC alarm day of month register.
|
||||
*/
|
||||
uint8_t aldom;
|
||||
/**
|
||||
* @brief RTC alarm month register.
|
||||
*/
|
||||
uint8_t almonth;
|
||||
/**
|
||||
* @brief RTC alarm day of week register.
|
||||
*/
|
||||
uint8_t aldow;
|
||||
/**
|
||||
* @brief RTC alarm year register.
|
||||
*/
|
||||
uint16_t alyear;
|
||||
/**
|
||||
* @brief RTC alarm day of year register.
|
||||
*/
|
||||
uint16_t aldoy;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing an RTC driver.
|
||||
*/
|
||||
struct RTCDriver{
|
||||
/**
|
||||
* @brief Callback pointer.
|
||||
*/
|
||||
rtccb_t callback;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern RTCDriver RTCD1;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void rtc_lld_init(void);
|
||||
void rtc_lld_set_time(RTCDriver *rtcp, const RTCTime *timespec);
|
||||
void rtc_lld_get_time(RTCDriver *rtcp, RTCTime *timespec);
|
||||
void rtc_lld_set_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
const RTCAlarm *alarmspec);
|
||||
void rtc_lld_get_alarm(RTCDriver *rtcp,
|
||||
rtcalarm_t alarm,
|
||||
RTCAlarm *alarmspec);
|
||||
void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
|
||||
uint32_t rtc_lld_get_time_fat(RTCDriver *rtcp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_RTC */
|
||||
|
||||
#endif /* _RTC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,476 +1,476 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/serial_lld.c
|
||||
* @brief LPC17xx low level serial driver code.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
/** @brief UART0 serial driver identifier.*/
|
||||
SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
/** @brief UART1 serial driver identifier.*/
|
||||
SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
/** @brief UART2 serial driver identifier.*/
|
||||
SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
/** @brief UART3 serial driver identifier.*/
|
||||
SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief Driver default configuration.*/
|
||||
static const SerialConfig default_config = {
|
||||
SERIAL_DEFAULT_BITRATE,
|
||||
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
|
||||
FCR_TRIGGER0
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART initialization.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] config the architecture-dependent serial driver configuration
|
||||
*/
|
||||
static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
uint32_t div = 0;
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART0_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART1_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART2_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART3_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
u->LCR = config->sc_lcr | LCR_DLAB;
|
||||
u->DLL = div;
|
||||
u->DLM = div >> 8;
|
||||
u->LCR = config->sc_lcr;
|
||||
u->FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_fcr;
|
||||
u->ACR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->TER = TER_ENABLE;
|
||||
u->IER = IER_RBR | IER_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART de-initialization.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
*/
|
||||
static void uart_deinit(LPC_UART_TypeDef *u) {
|
||||
|
||||
u->LCR = LCR_DLAB;
|
||||
u->DLL = 1;
|
||||
u->DLM = 0;
|
||||
u->LCR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->IER = 0;
|
||||
u->FCR = FCR_RXRESET | FCR_TXRESET;
|
||||
u->ACR = 0;
|
||||
u->TER = TER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error handling routine.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] err UART LSR register value
|
||||
*/
|
||||
static void set_error(SerialDriver *sdp, IOREG32 err) {
|
||||
flagsmask_t sts = 0;
|
||||
|
||||
if (err & LSR_OVERRUN)
|
||||
sts |= SD_OVERRUN_ERROR;
|
||||
if (err & LSR_PARITY)
|
||||
sts |= SD_PARITY_ERROR;
|
||||
if (err & LSR_FRAMING)
|
||||
sts |= SD_FRAMING_ERROR;
|
||||
if (err & LSR_BREAK)
|
||||
sts |= SD_BREAK_DETECTED;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, sts);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
* @note Tries hard to clear all the pending interrupt sources, we don't
|
||||
* want to go through the whole ISR and have another interrupt soon
|
||||
* after.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
*/
|
||||
static void serve_interrupt(SerialDriver *sdp) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
|
||||
while (TRUE) {
|
||||
switch (u->IIR & IIR_SRC_MASK) {
|
||||
case IIR_SRC_NONE:
|
||||
return;
|
||||
case IIR_SRC_ERROR:
|
||||
set_error(sdp, u->LSR);
|
||||
break;
|
||||
case IIR_SRC_TIMEOUT:
|
||||
case IIR_SRC_RX:
|
||||
chSysLockFromIsr();
|
||||
if (chIQIsEmptyI(&sdp->iqueue))
|
||||
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
|
||||
chSysUnlockFromIsr();
|
||||
while (u->LSR & LSR_RBR_FULL) {
|
||||
chSysLockFromIsr();
|
||||
if (chIQPutI(&sdp->iqueue, u->RBR) < Q_OK)
|
||||
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
break;
|
||||
case IIR_SRC_TX:
|
||||
{
|
||||
int i = LPC17xx_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b;
|
||||
|
||||
chSysLockFromIsr();
|
||||
b = chOQGetI(&sdp->oqueue);
|
||||
chSysUnlockFromIsr();
|
||||
if (b < Q_OK) {
|
||||
u->IER &= ~IER_THRE;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
chSysUnlockFromIsr();
|
||||
break;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
(void) u->THR;
|
||||
(void) u->RBR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts a TX FIFO preload.
|
||||
*/
|
||||
static void preload(SerialDriver *sdp) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
|
||||
if (u->LSR & LSR_THRE) {
|
||||
int i = LPC17xx_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b = chOQGetI(&sdp->oqueue);
|
||||
if (b < Q_OK) {
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
return;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
u->IER |= IER_THRE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Driver SD1 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
static void notify1(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD2 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
static void notify2(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD3 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
static void notify3(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD3);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD4 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
static void notify4(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD4);
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector54) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector58) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector5C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector60) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_init(void) {
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
sdObjectInit(&SD1, NULL, notify1);
|
||||
SD1.uart = (LPC_UART_TypeDef*) LPC_UART0;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
sdObjectInit(&SD2, NULL, notify2);
|
||||
SD2.uart = (LPC_UART_TypeDef*) LPC_UART1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
sdObjectInit(&SD3, NULL, notify3);
|
||||
SD3.uart = (LPC_UART_TypeDef*) LPC_UART2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
sdObjectInit(&SD4, NULL, notify4);
|
||||
SD4.uart = (LPC_UART_TypeDef*) LPC_UART3;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver configuration and (re)start.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
* @param[in] config the architecture-dependent serial driver configuration.
|
||||
* If this parameter is set to @p NULL then a default
|
||||
* configuration is used.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
|
||||
if (config == NULL)
|
||||
config = &default_config;
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 3);
|
||||
nvicEnableVector(UART0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 4);
|
||||
nvicEnableVector(UART1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 24);
|
||||
nvicEnableVector(UART2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 25);
|
||||
nvicEnableVector(UART3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
uart_init(sdp, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver stop.
|
||||
* @details De-initializes the UART, stops the associated clock, resets the
|
||||
* interrupt vector.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_stop(SerialDriver *sdp) {
|
||||
|
||||
if (sdp->state == SD_READY) {
|
||||
uart_deinit(sdp->uart);
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 3);
|
||||
nvicDisableVector(UART0_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 4);
|
||||
nvicDisableVector(UART1_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 24);
|
||||
nvicDisableVector(UART2_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 25);
|
||||
nvicDisableVector(UART3_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/serial_lld.c
|
||||
* @brief LPC17xx low level serial driver code.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
/** @brief UART0 serial driver identifier.*/
|
||||
SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
/** @brief UART1 serial driver identifier.*/
|
||||
SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
/** @brief UART2 serial driver identifier.*/
|
||||
SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
/** @brief UART3 serial driver identifier.*/
|
||||
SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief Driver default configuration.*/
|
||||
static const SerialConfig default_config = {
|
||||
SERIAL_DEFAULT_BITRATE,
|
||||
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
|
||||
FCR_TRIGGER0
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART initialization.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] config the architecture-dependent serial driver configuration
|
||||
*/
|
||||
static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
uint32_t div = 0;
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART0_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART1_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART2_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
div = LPC17xx_SERIAL_UART3_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
u->LCR = config->sc_lcr | LCR_DLAB;
|
||||
u->DLL = div;
|
||||
u->DLM = div >> 8;
|
||||
u->LCR = config->sc_lcr;
|
||||
u->FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_fcr;
|
||||
u->ACR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->TER = TER_ENABLE;
|
||||
u->IER = IER_RBR | IER_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART de-initialization.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
*/
|
||||
static void uart_deinit(LPC_UART_TypeDef *u) {
|
||||
|
||||
u->LCR = LCR_DLAB;
|
||||
u->DLL = 1;
|
||||
u->DLM = 0;
|
||||
u->LCR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->IER = 0;
|
||||
u->FCR = FCR_RXRESET | FCR_TXRESET;
|
||||
u->ACR = 0;
|
||||
u->TER = TER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error handling routine.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] err UART LSR register value
|
||||
*/
|
||||
static void set_error(SerialDriver *sdp, IOREG32 err) {
|
||||
flagsmask_t sts = 0;
|
||||
|
||||
if (err & LSR_OVERRUN)
|
||||
sts |= SD_OVERRUN_ERROR;
|
||||
if (err & LSR_PARITY)
|
||||
sts |= SD_PARITY_ERROR;
|
||||
if (err & LSR_FRAMING)
|
||||
sts |= SD_FRAMING_ERROR;
|
||||
if (err & LSR_BREAK)
|
||||
sts |= SD_BREAK_DETECTED;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, sts);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
* @note Tries hard to clear all the pending interrupt sources, we don't
|
||||
* want to go through the whole ISR and have another interrupt soon
|
||||
* after.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
*/
|
||||
static void serve_interrupt(SerialDriver *sdp) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
|
||||
while (TRUE) {
|
||||
switch (u->IIR & IIR_SRC_MASK) {
|
||||
case IIR_SRC_NONE:
|
||||
return;
|
||||
case IIR_SRC_ERROR:
|
||||
set_error(sdp, u->LSR);
|
||||
break;
|
||||
case IIR_SRC_TIMEOUT:
|
||||
case IIR_SRC_RX:
|
||||
chSysLockFromIsr();
|
||||
if (chIQIsEmptyI(&sdp->iqueue))
|
||||
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
|
||||
chSysUnlockFromIsr();
|
||||
while (u->LSR & LSR_RBR_FULL) {
|
||||
chSysLockFromIsr();
|
||||
if (chIQPutI(&sdp->iqueue, u->RBR) < Q_OK)
|
||||
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
break;
|
||||
case IIR_SRC_TX:
|
||||
{
|
||||
int i = LPC17xx_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b;
|
||||
|
||||
chSysLockFromIsr();
|
||||
b = chOQGetI(&sdp->oqueue);
|
||||
chSysUnlockFromIsr();
|
||||
if (b < Q_OK) {
|
||||
u->IER &= ~IER_THRE;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
chSysUnlockFromIsr();
|
||||
break;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
(void) u->THR;
|
||||
(void) u->RBR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts a TX FIFO preload.
|
||||
*/
|
||||
static void preload(SerialDriver *sdp) {
|
||||
LPC_UART_TypeDef *u = sdp->uart;
|
||||
|
||||
if (u->LSR & LSR_THRE) {
|
||||
int i = LPC17xx_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b = chOQGetI(&sdp->oqueue);
|
||||
if (b < Q_OK) {
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
return;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
u->IER |= IER_THRE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Driver SD1 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
static void notify1(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD2 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
static void notify2(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD3 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
static void notify3(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD3);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD4 output notification.
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
static void notify4(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD4);
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector54) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector58) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector5C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC17xx_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(Vector60) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_init(void) {
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
sdObjectInit(&SD1, NULL, notify1);
|
||||
SD1.uart = (LPC_UART_TypeDef*) LPC_UART0;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
sdObjectInit(&SD2, NULL, notify2);
|
||||
SD2.uart = (LPC_UART_TypeDef*) LPC_UART1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
sdObjectInit(&SD3, NULL, notify3);
|
||||
SD3.uart = (LPC_UART_TypeDef*) LPC_UART2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
sdObjectInit(&SD4, NULL, notify4);
|
||||
SD4.uart = (LPC_UART_TypeDef*) LPC_UART3;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver configuration and (re)start.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
* @param[in] config the architecture-dependent serial driver configuration.
|
||||
* If this parameter is set to @p NULL then a default
|
||||
* configuration is used.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
|
||||
if (config == NULL)
|
||||
config = &default_config;
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 3);
|
||||
nvicEnableVector(UART0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 4);
|
||||
nvicEnableVector(UART1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 24);
|
||||
nvicEnableVector(UART2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_SC->PCONP |= (1 << 25);
|
||||
nvicEnableVector(UART3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SERIAL_UART3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
uart_init(sdp, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver stop.
|
||||
* @details De-initializes the UART, stops the associated clock, resets the
|
||||
* interrupt vector.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_stop(SerialDriver *sdp) {
|
||||
|
||||
if (sdp->state == SD_READY) {
|
||||
uart_deinit(sdp->uart);
|
||||
#if LPC17xx_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 3);
|
||||
nvicDisableVector(UART0_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 4);
|
||||
nvicDisableVector(UART1_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 24);
|
||||
nvicDisableVector(UART2_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_SC->PCONP &= ~(1 << 25);
|
||||
nvicDisableVector(UART3_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,268 +1,268 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/serial_lld.h
|
||||
* @brief LPC17xx low level serial driver header.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_LLD_H_
|
||||
#define _SERIAL_LLD_H_
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define IIR_SRC_MASK 0x0F
|
||||
#define IIR_SRC_NONE 0x01
|
||||
#define IIR_SRC_MODEM 0x00
|
||||
#define IIR_SRC_TX 0x02
|
||||
#define IIR_SRC_RX 0x04
|
||||
#define IIR_SRC_ERROR 0x06
|
||||
#define IIR_SRC_TIMEOUT 0x0C
|
||||
|
||||
#define IER_RBR 1
|
||||
#define IER_THRE 2
|
||||
#define IER_STATUS 4
|
||||
|
||||
#define LCR_WL5 0
|
||||
#define LCR_WL6 1
|
||||
#define LCR_WL7 2
|
||||
#define LCR_WL8 3
|
||||
#define LCR_STOP1 0
|
||||
#define LCR_STOP2 4
|
||||
#define LCR_NOPARITY 0
|
||||
#define LCR_PARITYODD 0x08
|
||||
#define LCR_PARITYEVEN 0x18
|
||||
#define LCR_PARITYONE 0x28
|
||||
#define LCR_PARITYZERO 0x38
|
||||
#define LCR_BREAK_ON 0x40
|
||||
#define LCR_DLAB 0x80
|
||||
|
||||
#define FCR_ENABLE 1
|
||||
#define FCR_RXRESET 2
|
||||
#define FCR_TXRESET 4
|
||||
#define FCR_TRIGGER0 0
|
||||
#define FCR_TRIGGER1 0x40
|
||||
#define FCR_TRIGGER2 0x80
|
||||
#define FCR_TRIGGER3 0xC0
|
||||
|
||||
#define LSR_RBR_FULL 1
|
||||
#define LSR_OVERRUN 2
|
||||
#define LSR_PARITY 4
|
||||
#define LSR_FRAMING 8
|
||||
#define LSR_BREAK 0x10
|
||||
#define LSR_THRE 0x20
|
||||
#define LSR_TEMT 0x40
|
||||
#define LSR_RXFE 0x80
|
||||
|
||||
#define TER_ENABLE 0x80
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART0 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART1 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART2 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART3 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART3) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief FIFO preload parameter.
|
||||
* @details Configuration parameter, this values defines how many bytes are
|
||||
* preloaded in the HW transmit FIFO for each interrupt, the maximum
|
||||
* value is 16 the minimum is 1.
|
||||
* @note An high value reduces the number of interrupts generated but can
|
||||
* also increase the worst case interrupt response time because the
|
||||
* preload loops.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_FIFO_PRELOAD) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_FIFO_PRELOAD 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
#if (LPC17xx_SERIAL_FIFO_PRELOAD < 1) || (LPC17xx_SERIAL_FIFO_PRELOAD > 16)
|
||||
#error "invalid LPC17xx_SERIAL_FIFO_PRELOAD setting"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART0_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART1 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART1_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART2 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART2_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART3 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART3_PCLK LPC17xx_PCLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx Serial Driver configuration structure.
|
||||
* @details An instance of this structure must be passed to @p sdStart()
|
||||
* in order to configure and start a serial driver operations.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Bit rate.
|
||||
*/
|
||||
uint32_t sc_speed;
|
||||
/**
|
||||
* @brief Initialization value for the LCR register.
|
||||
*/
|
||||
uint32_t sc_lcr;
|
||||
/**
|
||||
* @brief Initialization value for the FCR register.
|
||||
*/
|
||||
uint32_t sc_fcr;
|
||||
} SerialConfig;
|
||||
|
||||
/**
|
||||
* @brief @p SerialDriver specific data.
|
||||
*/
|
||||
#define _serial_driver_data \
|
||||
_base_asynchronous_channel_data \
|
||||
/* Driver state.*/ \
|
||||
sdstate_t state; \
|
||||
/* Input queue.*/ \
|
||||
InputQueue iqueue; \
|
||||
/* Output queue.*/ \
|
||||
OutputQueue oqueue; \
|
||||
/* Input circular buffer.*/ \
|
||||
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
|
||||
/* Output circular buffer.*/ \
|
||||
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
|
||||
/* End of the mandatory fields.*/ \
|
||||
/* Pointer to the USART registers block.*/ \
|
||||
LPC_UART_TypeDef *uart;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void sd_lld_init(void);
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
|
||||
void sd_lld_stop(SerialDriver *sdp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
#endif /* _SERIAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/serial_lld.h
|
||||
* @brief LPC17xx low level serial driver header.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_LLD_H_
|
||||
#define _SERIAL_LLD_H_
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define IIR_SRC_MASK 0x0F
|
||||
#define IIR_SRC_NONE 0x01
|
||||
#define IIR_SRC_MODEM 0x00
|
||||
#define IIR_SRC_TX 0x02
|
||||
#define IIR_SRC_RX 0x04
|
||||
#define IIR_SRC_ERROR 0x06
|
||||
#define IIR_SRC_TIMEOUT 0x0C
|
||||
|
||||
#define IER_RBR 1
|
||||
#define IER_THRE 2
|
||||
#define IER_STATUS 4
|
||||
|
||||
#define LCR_WL5 0
|
||||
#define LCR_WL6 1
|
||||
#define LCR_WL7 2
|
||||
#define LCR_WL8 3
|
||||
#define LCR_STOP1 0
|
||||
#define LCR_STOP2 4
|
||||
#define LCR_NOPARITY 0
|
||||
#define LCR_PARITYODD 0x08
|
||||
#define LCR_PARITYEVEN 0x18
|
||||
#define LCR_PARITYONE 0x28
|
||||
#define LCR_PARITYZERO 0x38
|
||||
#define LCR_BREAK_ON 0x40
|
||||
#define LCR_DLAB 0x80
|
||||
|
||||
#define FCR_ENABLE 1
|
||||
#define FCR_RXRESET 2
|
||||
#define FCR_TXRESET 4
|
||||
#define FCR_TRIGGER0 0
|
||||
#define FCR_TRIGGER1 0x40
|
||||
#define FCR_TRIGGER2 0x80
|
||||
#define FCR_TRIGGER3 0xC0
|
||||
|
||||
#define LSR_RBR_FULL 1
|
||||
#define LSR_OVERRUN 2
|
||||
#define LSR_PARITY 4
|
||||
#define LSR_FRAMING 8
|
||||
#define LSR_BREAK 0x10
|
||||
#define LSR_THRE 0x20
|
||||
#define LSR_TEMT 0x40
|
||||
#define LSR_RXFE 0x80
|
||||
|
||||
#define TER_ENABLE 0x80
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART0 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART1 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART2 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART2) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART3 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_USE_UART3) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_USE_UART3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief FIFO preload parameter.
|
||||
* @details Configuration parameter, this values defines how many bytes are
|
||||
* preloaded in the HW transmit FIFO for each interrupt, the maximum
|
||||
* value is 16 the minimum is 1.
|
||||
* @note An high value reduces the number of interrupts generated but can
|
||||
* also increase the worst case interrupt response time because the
|
||||
* preload loops.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_FIFO_PRELOAD) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_FIFO_PRELOAD 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SERIAL_UART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
#if (LPC17xx_SERIAL_FIFO_PRELOAD < 1) || (LPC17xx_SERIAL_FIFO_PRELOAD > 16)
|
||||
#error "invalid LPC17xx_SERIAL_FIFO_PRELOAD setting"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART0_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART1 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART1_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART2 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART2_PCLK LPC17xx_PCLK
|
||||
|
||||
/**
|
||||
* @brief UART3 clock.
|
||||
*/
|
||||
#define LPC17xx_SERIAL_UART3_PCLK LPC17xx_PCLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx Serial Driver configuration structure.
|
||||
* @details An instance of this structure must be passed to @p sdStart()
|
||||
* in order to configure and start a serial driver operations.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Bit rate.
|
||||
*/
|
||||
uint32_t sc_speed;
|
||||
/**
|
||||
* @brief Initialization value for the LCR register.
|
||||
*/
|
||||
uint32_t sc_lcr;
|
||||
/**
|
||||
* @brief Initialization value for the FCR register.
|
||||
*/
|
||||
uint32_t sc_fcr;
|
||||
} SerialConfig;
|
||||
|
||||
/**
|
||||
* @brief @p SerialDriver specific data.
|
||||
*/
|
||||
#define _serial_driver_data \
|
||||
_base_asynchronous_channel_data \
|
||||
/* Driver state.*/ \
|
||||
sdstate_t state; \
|
||||
/* Input queue.*/ \
|
||||
InputQueue iqueue; \
|
||||
/* Output queue.*/ \
|
||||
OutputQueue oqueue; \
|
||||
/* Input circular buffer.*/ \
|
||||
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
|
||||
/* Output circular buffer.*/ \
|
||||
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
|
||||
/* End of the mandatory fields.*/ \
|
||||
/* Pointer to the USART registers block.*/ \
|
||||
LPC_UART_TypeDef *uart;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void sd_lld_init(void);
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
|
||||
void sd_lld_stop(SerialDriver *sdp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
#endif /* _SERIAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,387 +1,387 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/spi_lld.c
|
||||
* @brief LPC17xx low level SPI driver code.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/** @brief SPI1 driver identifier.*/
|
||||
SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/** @brief SPI2 driver identifier.*/
|
||||
SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Preloads the transmit FIFO.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void ssp_fifo_preload(SPIDriver *spip) {
|
||||
LPC_SSP_TypeDef *ssp = spip->ssp;
|
||||
uint32_t n = spip->txcnt > LPC17xx_SSP_FIFO_DEPTH ?
|
||||
LPC17xx_SSP_FIFO_DEPTH : spip->txcnt;
|
||||
|
||||
while(((ssp->SR & SR_TNF) != 0) && (n > 0)) {
|
||||
if (spip->txptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
const uint16_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
else {
|
||||
const uint8_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
ssp->DR = 0xFFFFFFFF;
|
||||
n--;
|
||||
spip->txcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void spi_serve_interrupt(SPIDriver *spip) {
|
||||
LPC_SSP_TypeDef *ssp = spip->ssp;
|
||||
|
||||
if ((ssp->MIS & MIS_ROR) != 0) {
|
||||
/* The overflow condition should never happen because priority is given
|
||||
to receive but a hook macro is provided anyway...*/
|
||||
LPC17xx_SPI_SSP_ERROR_HOOK(spip);
|
||||
}
|
||||
ssp->ICR = ICR_RT | ICR_ROR;
|
||||
while ((ssp->SR & SR_RNE) != 0) {
|
||||
if (spip->rxptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
uint16_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
else {
|
||||
uint8_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
(void)ssp->DR;
|
||||
if (--spip->rxcnt == 0) {
|
||||
chDbgAssert(spip->txcnt == 0,
|
||||
"spi_serve_interrupt(), #1", "counter out of synch");
|
||||
/* Stops the IRQ sources.*/
|
||||
ssp->IMSC = 0;
|
||||
/* Portable SPI ISR code defined in the high level driver, note, it is
|
||||
a macro.*/
|
||||
_spi_isr_code(spip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssp_fifo_preload(spip);
|
||||
if (spip->txcnt == 0)
|
||||
ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector78) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector7C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level SPI driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.ssp = LPC_SSP0;
|
||||
#endif /* LPC17xx_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
spiObjectInit(&SPID2);
|
||||
SPID2.ssp = LPC_SSP1;
|
||||
#endif /* LPC17xx_SPI_USE_SSP0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_start(SPIDriver *spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_SC->PCONP |= (1UL << 21);
|
||||
LPC_SC->PCLKSEL0 &= (PCLKSEL_MASK << 20);
|
||||
LPC_SC->PCLKSEL0 |= (LPC17xx_SPI_SSP0_PCLKSEL << 20);
|
||||
nvicEnableVector(SSP0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SPI_SSP0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_SC->PCONP |= (1UL << 10);
|
||||
LPC_SC->PCLKSEL1 &= (PCLKSEL_MASK << 10);
|
||||
LPC_SC->PCLKSEL1 |= (LPC17xx_SPI_SSP0_PCLKSEL << 10);
|
||||
nvicEnableVector(SSP1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SPI_SSP1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Configuration.*/
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->ICR = ICR_RT | ICR_ROR;
|
||||
spip->ssp->CR0 = spip->config->cr0;
|
||||
spip->ssp->CPSR = spip->config->cpsr;
|
||||
spip->ssp->CR1 = CR1_SSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_stop(SPIDriver *spip) {
|
||||
|
||||
if (spip->state != SPI_STOP) {
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->CR0 = 0;
|
||||
spip->ssp->CPSR = 0;
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_SC->PCONP &= ~(1UL << 21);
|
||||
nvicDisableVector(SSP0_IRQn);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_SC->PCONP &= ~(1UL << 10);
|
||||
nvicDisableVector(SSP1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts the slave select signal and prepares for transfers.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_select(SPIDriver *spip) {
|
||||
|
||||
palClearPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deasserts the slave select signal.
|
||||
* @details The previously selected peripheral is unselected.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_unselect(SPIDriver *spip) {
|
||||
|
||||
palSetPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ignores data on the SPI bus.
|
||||
* @details This function transmits a series of idle words on the SPI bus and
|
||||
* ignores the received data. This function can be invoked even
|
||||
* when a slave select signal has not been yet asserted.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be ignored
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges data on the SPI bus.
|
||||
* @details This asynchronous function starts a simultaneous transmit/receive
|
||||
* operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the SPI bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from the SPI bus.
|
||||
* @details This asynchronous function starts a receive operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to receive
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges one frame using a polled wait.
|
||||
* @details This synchronous function exchanges one frame using a polled
|
||||
* synchronization method. This function is useful when exchanging
|
||||
* small amount of data on high speed channels, usually in this
|
||||
* situation is much more efficient just wait for completion using
|
||||
* polling than suspending the thread waiting for an interrupt.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] frame the data frame to send over the SPI bus
|
||||
* @return The received data frame from the SPI bus.
|
||||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
|
||||
|
||||
spip->ssp->DR = (uint32_t)frame;
|
||||
while ((spip->ssp->SR & SR_RNE) == 0)
|
||||
;
|
||||
return (uint16_t)spip->ssp->DR;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/spi_lld.c
|
||||
* @brief LPC17xx low level SPI driver code.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/** @brief SPI1 driver identifier.*/
|
||||
SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/** @brief SPI2 driver identifier.*/
|
||||
SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Preloads the transmit FIFO.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void ssp_fifo_preload(SPIDriver *spip) {
|
||||
LPC_SSP_TypeDef *ssp = spip->ssp;
|
||||
uint32_t n = spip->txcnt > LPC17xx_SSP_FIFO_DEPTH ?
|
||||
LPC17xx_SSP_FIFO_DEPTH : spip->txcnt;
|
||||
|
||||
while(((ssp->SR & SR_TNF) != 0) && (n > 0)) {
|
||||
if (spip->txptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
const uint16_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
else {
|
||||
const uint8_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
ssp->DR = 0xFFFFFFFF;
|
||||
n--;
|
||||
spip->txcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void spi_serve_interrupt(SPIDriver *spip) {
|
||||
LPC_SSP_TypeDef *ssp = spip->ssp;
|
||||
|
||||
if ((ssp->MIS & MIS_ROR) != 0) {
|
||||
/* The overflow condition should never happen because priority is given
|
||||
to receive but a hook macro is provided anyway...*/
|
||||
LPC17xx_SPI_SSP_ERROR_HOOK(spip);
|
||||
}
|
||||
ssp->ICR = ICR_RT | ICR_ROR;
|
||||
while ((ssp->SR & SR_RNE) != 0) {
|
||||
if (spip->rxptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
uint16_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
else {
|
||||
uint8_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
(void)ssp->DR;
|
||||
if (--spip->rxcnt == 0) {
|
||||
chDbgAssert(spip->txcnt == 0,
|
||||
"spi_serve_interrupt(), #1", "counter out of synch");
|
||||
/* Stops the IRQ sources.*/
|
||||
ssp->IMSC = 0;
|
||||
/* Portable SPI ISR code defined in the high level driver, note, it is
|
||||
a macro.*/
|
||||
_spi_isr_code(spip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssp_fifo_preload(spip);
|
||||
if (spip->txcnt == 0)
|
||||
ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector78) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector7C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level SPI driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.ssp = LPC_SSP0;
|
||||
#endif /* LPC17xx_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
spiObjectInit(&SPID2);
|
||||
SPID2.ssp = LPC_SSP1;
|
||||
#endif /* LPC17xx_SPI_USE_SSP0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_start(SPIDriver *spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_SC->PCONP |= (1UL << 21);
|
||||
LPC_SC->PCLKSEL0 &= (PCLKSEL_MASK << 20);
|
||||
LPC_SC->PCLKSEL0 |= (LPC17xx_SPI_SSP0_PCLKSEL << 20);
|
||||
nvicEnableVector(SSP0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SPI_SSP0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_SC->PCONP |= (1UL << 10);
|
||||
LPC_SC->PCLKSEL1 &= (PCLKSEL_MASK << 10);
|
||||
LPC_SC->PCLKSEL1 |= (LPC17xx_SPI_SSP0_PCLKSEL << 10);
|
||||
nvicEnableVector(SSP1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC17xx_SPI_SSP1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Configuration.*/
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->ICR = ICR_RT | ICR_ROR;
|
||||
spip->ssp->CR0 = spip->config->cr0;
|
||||
spip->ssp->CPSR = spip->config->cpsr;
|
||||
spip->ssp->CR1 = CR1_SSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_stop(SPIDriver *spip) {
|
||||
|
||||
if (spip->state != SPI_STOP) {
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->CR0 = 0;
|
||||
spip->ssp->CPSR = 0;
|
||||
#if LPC17xx_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_SC->PCONP &= ~(1UL << 21);
|
||||
nvicDisableVector(SSP0_IRQn);
|
||||
}
|
||||
#endif
|
||||
#if LPC17xx_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_SC->PCONP &= ~(1UL << 10);
|
||||
nvicDisableVector(SSP1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts the slave select signal and prepares for transfers.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_select(SPIDriver *spip) {
|
||||
|
||||
palClearPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deasserts the slave select signal.
|
||||
* @details The previously selected peripheral is unselected.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_unselect(SPIDriver *spip) {
|
||||
|
||||
palSetPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ignores data on the SPI bus.
|
||||
* @details This function transmits a series of idle words on the SPI bus and
|
||||
* ignores the received data. This function can be invoked even
|
||||
* when a slave select signal has not been yet asserted.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be ignored
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges data on the SPI bus.
|
||||
* @details This asynchronous function starts a simultaneous transmit/receive
|
||||
* operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the SPI bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from the SPI bus.
|
||||
* @details This asynchronous function starts a receive operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to receive
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges one frame using a polled wait.
|
||||
* @details This synchronous function exchanges one frame using a polled
|
||||
* synchronization method. This function is useful when exchanging
|
||||
* small amount of data on high speed channels, usually in this
|
||||
* situation is much more efficient just wait for completion using
|
||||
* polling than suspending the thread waiting for an interrupt.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] frame the data frame to send over the SPI bus
|
||||
* @return The received data frame from the SPI bus.
|
||||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
|
||||
|
||||
spip->ssp->DR = (uint32_t)frame;
|
||||
while ((spip->ssp->SR & SR_RNE) == 0)
|
||||
;
|
||||
return (uint16_t)spip->ssp->DR;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,337 +1,337 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/spi_lld.h
|
||||
* @brief LPC17xx low level SPI driver header.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SPI_LLD_H_
|
||||
#define _SPI_LLD_H_
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Hardware FIFO depth.
|
||||
*/
|
||||
#define LPC17xx_SSP_FIFO_DEPTH 8
|
||||
|
||||
#define CR0_DSSMASK 0x0F
|
||||
#define CR0_DSS4BIT 3
|
||||
#define CR0_DSS5BIT 4
|
||||
#define CR0_DSS6BIT 5
|
||||
#define CR0_DSS7BIT 6
|
||||
#define CR0_DSS8BIT 7
|
||||
#define CR0_DSS9BIT 8
|
||||
#define CR0_DSS10BIT 9
|
||||
#define CR0_DSS11BIT 0xA
|
||||
#define CR0_DSS12BIT 0xB
|
||||
#define CR0_DSS13BIT 0xC
|
||||
#define CR0_DSS14BIT 0xD
|
||||
#define CR0_DSS15BIT 0xE
|
||||
#define CR0_DSS16BIT 0xF
|
||||
#define CR0_FRFSPI 0
|
||||
#define CR0_FRFSSI 0x10
|
||||
#define CR0_FRFMW 0x20
|
||||
#define CR0_CPOL 0x40
|
||||
#define CR0_CPHA 0x80
|
||||
#define CR0_CLOCKRATE(n) ((n) << 8)
|
||||
|
||||
#define CR1_LBM 1
|
||||
#define CR1_SSE 2
|
||||
#define CR1_MS 4
|
||||
#define CR1_SOD 8
|
||||
|
||||
#define SR_TFE 1
|
||||
#define SR_TNF 2
|
||||
#define SR_RNE 4
|
||||
#define SR_RFF 8
|
||||
#define SR_BSY 16
|
||||
|
||||
#define IMSC_ROR 1
|
||||
#define IMSC_RT 2
|
||||
#define IMSC_RX 4
|
||||
#define IMSC_TX 8
|
||||
|
||||
#define RIS_ROR 1
|
||||
#define RIS_RT 2
|
||||
#define RIS_RX 4
|
||||
#define RIS_TX 8
|
||||
|
||||
#define MIS_ROR 1
|
||||
#define MIS_RT 2
|
||||
#define MIS_RX 4
|
||||
#define MIS_TX 8
|
||||
|
||||
#define ICR_ROR 1
|
||||
#define ICR_RT 2
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief SPI1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP0 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_USE_SSP0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_USE_SSP0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_USE_SSP1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_USE_SSP1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP0CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP0CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP1 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP1CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP1CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP0_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overflow error hook.
|
||||
* @details The default action is to stop the system.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_SSP0CLKDIV == 1
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 2
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_2
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 4
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_4
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 8
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_8
|
||||
#else
|
||||
#error "Invalid LPC17xx_SPI_SSP0CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_SSP1CLKDIV == 1
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 2
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_2
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 4
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_4
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 8
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_8
|
||||
#else
|
||||
#error "Invalid LPC17xx_SPI_SSP1CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (LPC17xx_SPI_SSP0CLKDIV != 1) && (LPC17xx_SPI_SSP0CLKDIV != 2) && \
|
||||
(LPC17xx_SPI_SSP0CLKDIV != 4) && (LPC17xx_SPI_SSP0CLKDIV != 8)
|
||||
#error "Invalid LPC17xx_SPI_SSP0CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if (LPC17xx_SPI_SSP1CLKDIV != 1) && (LPC17xx_SPI_SSP1CLKDIV != 2) && \
|
||||
(LPC17xx_SPI_SSP1CLKDIV != 4) && (LPC17xx_SPI_SSP1CLKDIV != 8)
|
||||
#error "invalid LPC17xx_SPI_SSP1CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if !LPC17xx_SPI_USE_SSP0 && !LPC17xx_SPI_USE_SSP1
|
||||
#error "SPI driver activated but no SPI peripheral assigned"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 clock.
|
||||
*/
|
||||
#define LPC17xx_SPI_SSP0_PCLK \
|
||||
(LPC17xx_CCLK / LPC17xx_SPI_SSP0CLKDIV)
|
||||
|
||||
/**
|
||||
* @brief SSP1 clock.
|
||||
*/
|
||||
#define LPC17xx_SPI_SSP1_PCLK \
|
||||
(LPC17xx_CCLK / LPC17xx_SPI_SSP1CLKDIV)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
typedef struct SPIDriver SPIDriver;
|
||||
|
||||
/**
|
||||
* @brief SPI notification callback type.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*spicallback_t)(SPIDriver *spip);
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
spicallback_t end_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief The chip select line port.
|
||||
*/
|
||||
ioportid_t ssport;
|
||||
/**
|
||||
* @brief The chip select line pad number.
|
||||
*/
|
||||
uint16_t sspad;
|
||||
/**
|
||||
* @brief SSP CR0 initialization data.
|
||||
*/
|
||||
uint16_t cr0;
|
||||
/**
|
||||
* @brief SSP CPSR initialization data.
|
||||
*/
|
||||
uint32_t cpsr;
|
||||
} SPIConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a SPI driver.
|
||||
*/
|
||||
struct SPIDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
spistate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const SPIConfig *config;
|
||||
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* SPI_USE_WAIT */
|
||||
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* SPI_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(SPI_DRIVER_EXT_FIELDS)
|
||||
SPI_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the SSP registers block.
|
||||
*/
|
||||
LPC_SSP_TypeDef *ssp;
|
||||
/**
|
||||
* @brief Number of bytes yet to be received.
|
||||
*/
|
||||
uint32_t rxcnt;
|
||||
/**
|
||||
* @brief Receive pointer or @p NULL.
|
||||
*/
|
||||
void *rxptr;
|
||||
/**
|
||||
* @brief Number of bytes yet to be transmitted.
|
||||
*/
|
||||
uint32_t txcnt;
|
||||
/**
|
||||
* @brief Transmit pointer or @p NULL.
|
||||
*/
|
||||
const void *txptr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_lld_init(void);
|
||||
void spi_lld_start(SPIDriver *spip);
|
||||
void spi_lld_stop(SPIDriver *spip);
|
||||
void spi_lld_select(SPIDriver *spip);
|
||||
void spi_lld_unselect(SPIDriver *spip);
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n);
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf);
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
#endif /* _SPI_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC17xx/spi_lld.h
|
||||
* @brief LPC17xx low level SPI driver header.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SPI_LLD_H_
|
||||
#define _SPI_LLD_H_
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Hardware FIFO depth.
|
||||
*/
|
||||
#define LPC17xx_SSP_FIFO_DEPTH 8
|
||||
|
||||
#define CR0_DSSMASK 0x0F
|
||||
#define CR0_DSS4BIT 3
|
||||
#define CR0_DSS5BIT 4
|
||||
#define CR0_DSS6BIT 5
|
||||
#define CR0_DSS7BIT 6
|
||||
#define CR0_DSS8BIT 7
|
||||
#define CR0_DSS9BIT 8
|
||||
#define CR0_DSS10BIT 9
|
||||
#define CR0_DSS11BIT 0xA
|
||||
#define CR0_DSS12BIT 0xB
|
||||
#define CR0_DSS13BIT 0xC
|
||||
#define CR0_DSS14BIT 0xD
|
||||
#define CR0_DSS15BIT 0xE
|
||||
#define CR0_DSS16BIT 0xF
|
||||
#define CR0_FRFSPI 0
|
||||
#define CR0_FRFSSI 0x10
|
||||
#define CR0_FRFMW 0x20
|
||||
#define CR0_CPOL 0x40
|
||||
#define CR0_CPHA 0x80
|
||||
#define CR0_CLOCKRATE(n) ((n) << 8)
|
||||
|
||||
#define CR1_LBM 1
|
||||
#define CR1_SSE 2
|
||||
#define CR1_MS 4
|
||||
#define CR1_SOD 8
|
||||
|
||||
#define SR_TFE 1
|
||||
#define SR_TNF 2
|
||||
#define SR_RNE 4
|
||||
#define SR_RFF 8
|
||||
#define SR_BSY 16
|
||||
|
||||
#define IMSC_ROR 1
|
||||
#define IMSC_RT 2
|
||||
#define IMSC_RX 4
|
||||
#define IMSC_TX 8
|
||||
|
||||
#define RIS_ROR 1
|
||||
#define RIS_RT 2
|
||||
#define RIS_RX 4
|
||||
#define RIS_TX 8
|
||||
|
||||
#define MIS_ROR 1
|
||||
#define MIS_RT 2
|
||||
#define MIS_RX 4
|
||||
#define MIS_TX 8
|
||||
|
||||
#define ICR_ROR 1
|
||||
#define ICR_RT 2
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief SPI1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP0 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_USE_SSP0) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_USE_SSP0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_USE_SSP1) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_USE_SSP1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP0CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP0CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP1 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP1CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP1CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP0_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overflow error hook.
|
||||
* @details The default action is to stop the system.
|
||||
*/
|
||||
#if !defined(LPC17xx_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define LPC17xx_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_SSP0CLKDIV == 1
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 2
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_2
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 4
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_4
|
||||
#elif LPC17xx_SPI_SSP0CLKDIV == 8
|
||||
#define LPC17xx_SPI_SSP0_PCLKSEL PCLKSEL_CCLK_DIV_8
|
||||
#else
|
||||
#error "Invalid LPC17xx_SPI_SSP0CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_SSP1CLKDIV == 1
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 2
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_2
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 4
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_4
|
||||
#elif LPC17xx_SPI_SSP1CLKDIV == 8
|
||||
#define LPC17xx_SPI_SSP1_PCLKSEL PCLKSEL_CCLK_DIV_8
|
||||
#else
|
||||
#error "Invalid LPC17xx_SPI_SSP1CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if (LPC17xx_SPI_SSP0CLKDIV != 1) && (LPC17xx_SPI_SSP0CLKDIV != 2) && \
|
||||
(LPC17xx_SPI_SSP0CLKDIV != 4) && (LPC17xx_SPI_SSP0CLKDIV != 8)
|
||||
#error "Invalid LPC17xx_SPI_SSP0CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if (LPC17xx_SPI_SSP1CLKDIV != 1) && (LPC17xx_SPI_SSP1CLKDIV != 2) && \
|
||||
(LPC17xx_SPI_SSP1CLKDIV != 4) && (LPC17xx_SPI_SSP1CLKDIV != 8)
|
||||
#error "invalid LPC17xx_SPI_SSP1CLKDIV setting (1, 2, 4 or 8 accepted)"
|
||||
#endif
|
||||
|
||||
#if !LPC17xx_SPI_USE_SSP0 && !LPC17xx_SPI_USE_SSP1
|
||||
#error "SPI driver activated but no SPI peripheral assigned"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 clock.
|
||||
*/
|
||||
#define LPC17xx_SPI_SSP0_PCLK \
|
||||
(LPC17xx_CCLK / LPC17xx_SPI_SSP0CLKDIV)
|
||||
|
||||
/**
|
||||
* @brief SSP1 clock.
|
||||
*/
|
||||
#define LPC17xx_SPI_SSP1_PCLK \
|
||||
(LPC17xx_CCLK / LPC17xx_SPI_SSP1CLKDIV)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
typedef struct SPIDriver SPIDriver;
|
||||
|
||||
/**
|
||||
* @brief SPI notification callback type.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*spicallback_t)(SPIDriver *spip);
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
spicallback_t end_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief The chip select line port.
|
||||
*/
|
||||
ioportid_t ssport;
|
||||
/**
|
||||
* @brief The chip select line pad number.
|
||||
*/
|
||||
uint16_t sspad;
|
||||
/**
|
||||
* @brief SSP CR0 initialization data.
|
||||
*/
|
||||
uint16_t cr0;
|
||||
/**
|
||||
* @brief SSP CPSR initialization data.
|
||||
*/
|
||||
uint32_t cpsr;
|
||||
} SPIConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a SPI driver.
|
||||
*/
|
||||
struct SPIDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
spistate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const SPIConfig *config;
|
||||
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* SPI_USE_WAIT */
|
||||
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* SPI_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(SPI_DRIVER_EXT_FIELDS)
|
||||
SPI_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the SSP registers block.
|
||||
*/
|
||||
LPC_SSP_TypeDef *ssp;
|
||||
/**
|
||||
* @brief Number of bytes yet to be received.
|
||||
*/
|
||||
uint32_t rxcnt;
|
||||
/**
|
||||
* @brief Receive pointer or @p NULL.
|
||||
*/
|
||||
void *rxptr;
|
||||
/**
|
||||
* @brief Number of bytes yet to be transmitted.
|
||||
*/
|
||||
uint32_t txcnt;
|
||||
/**
|
||||
* @brief Transmit pointer or @p NULL.
|
||||
*/
|
||||
const void *txptr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP0 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC17xx_SPI_USE_SSP1 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_lld_init(void);
|
||||
void spi_lld_start(SPIDriver *spip);
|
||||
void spi_lld_stop(SPIDriver *spip);
|
||||
void spi_lld_select(SPIDriver *spip);
|
||||
void spi_lld_unselect(SPIDriver *spip);
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n);
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf);
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
#endif /* _SPI_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
/**************************************************************************//**
|
||||
* @file system_LPC17xx.h
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File
|
||||
* for the NXP LPC17xx Device Series
|
||||
* @version V1.02
|
||||
* @date 08. September 2009
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009 ARM Limited. All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* ARM Limited (ARM) is supplying this software for use with Cortex-M
|
||||
* processor based microcontrollers. This file can be freely distributed
|
||||
* within development tools that are supporting such ARM based processors.
|
||||
*
|
||||
* @par
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __SYSTEM_LPC17xx_H
|
||||
#define __SYSTEM_LPC17xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System and update the SystemCoreClock variable.
|
||||
*/
|
||||
extern void SystemInit (void);
|
||||
|
||||
/**
|
||||
* Update SystemCoreClock variable
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Updates the SystemCoreClock with current core Clock
|
||||
* retrieved from cpu registers.
|
||||
*/
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_LPC17xx_H */
|
||||
/**************************************************************************//**
|
||||
* @file system_LPC17xx.h
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File
|
||||
* for the NXP LPC17xx Device Series
|
||||
* @version V1.02
|
||||
* @date 08. September 2009
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2009 ARM Limited. All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* ARM Limited (ARM) is supplying this software for use with Cortex-M
|
||||
* processor based microcontrollers. This file can be freely distributed
|
||||
* within development tools that are supporting such ARM based processors.
|
||||
*
|
||||
* @par
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __SYSTEM_LPC17xx_H
|
||||
#define __SYSTEM_LPC17xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System and update the SystemCoreClock variable.
|
||||
*/
|
||||
extern void SystemInit (void);
|
||||
|
||||
/**
|
||||
* Update SystemCoreClock variable
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Updates the SystemCoreClock with current core Clock
|
||||
* retrieved from cpu registers.
|
||||
*/
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_LPC17xx_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,212 +1,212 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/dac_lld.c
|
||||
* @brief LPC43xx DAC subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief CHN1 driver identifier.*/
|
||||
DACDriver DACD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc_dma_lli_config_t lpc_dac_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Shared end/half-of-tx service routine.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] flags pre-shifted content of the ISR register
|
||||
*/
|
||||
static void dac_serve_dma_interrupt(DACDriver *dacp, uint32_t flags) {
|
||||
|
||||
if ((flags & (1 << LPC_DAC_DMA_CHANNEL)) != 0) {
|
||||
_dac_isr_error_code(dacp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else {
|
||||
if (dacp->half_buffer == false) {
|
||||
_dac_isr_half_code(dacp);
|
||||
dacp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_dac_isr_full_code(dacp);
|
||||
dacp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level DAC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_init(void) {
|
||||
dacObjectInit(&DACD1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start(DACDriver *dacp) {
|
||||
|
||||
if (dacp->state == DAC_STOP) {
|
||||
|
||||
LPC_CCU1->CLK_APB3_DAC_CFG = 1; /* Enable clock. */
|
||||
LPC_DAC->CR = 0;
|
||||
LPC_DAC->CTRL = 0;
|
||||
LPC_DAC->CNTVAL = LPC_BASE_APB3_CLK/dacp->config->frequency;
|
||||
|
||||
dmaMuxSet(PERIPHERAL15, 0);
|
||||
dmaChannelAllocate(LPC_DAC_DMA_CHANNEL, \
|
||||
(lpc_dmaisr_t)dac_serve_dma_interrupt, \
|
||||
(void *)dacp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_stop(DACDriver *dacp) {
|
||||
|
||||
/* If in ready state then disables the DAC clock.*/
|
||||
if (dacp->state == DAC_READY) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC_DAC_DMA_CHANNEL);
|
||||
dmaChannelRelease(LPC_DAC_DMA_CHANNEL);
|
||||
|
||||
LPC_DAC->CTRL = 0; /* Disable DAC */
|
||||
LPC_CCU1->CLK_APB3_DAC_CFG = 0; /* Disable clock. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the DAC bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start_conversion(DACDriver *dacp) {
|
||||
|
||||
dacp->half_buffer = false;
|
||||
uint32_t dma_ch_config;
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_dac_lli[0].srcaddr = (uint32_t) &dacp->samples[0];
|
||||
lpc_dac_lli[0].dstaddr = (uint32_t)&LPC_DAC->CR;
|
||||
lpc_dac_lli[0].lli = (uint32_t) &lpc_dac_lli[1];
|
||||
lpc_dac_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(dacp->depth/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_AHBM0 |
|
||||
DMA_CTRL_DST_AHBM1 |
|
||||
DMA_CTRL_SRC_INC |
|
||||
DMA_CTRL_DST_NOINC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_dac_lli[1].srcaddr = (uint32_t) &dacp->samples[dacp->depth/2];
|
||||
lpc_dac_lli[1].dstaddr = lpc_dac_lli[0].dstaddr;
|
||||
lpc_dac_lli[1].control = lpc_dac_lli[0].control;
|
||||
|
||||
if (dacp->grpp->circular == true) {
|
||||
lpc_dac_lli[1].lli = (uint32_t) &lpc_dac_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_dac_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_DST_PERIPH(PERIPHERAL15) |
|
||||
DMA_CFG_FCTRL_M2P |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].lli, DMA_LLI_AHBM0);
|
||||
dmaChannelControl(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].control);
|
||||
dmaChannelConfig(LPC_DAC_DMA_CHANNEL, dma_ch_config);
|
||||
|
||||
LPC_DAC->CTRL = DACCTRL_DMA_ENA | DACCTRL_CNT_ENA | DACCTRL_DBLBUF_ENA;
|
||||
}
|
||||
|
||||
void dac_lld_stop_conversion(DACDriver *dacp) {
|
||||
|
||||
/* If in active state then disables the DAC.*/
|
||||
if (dacp->state == DAC_ACTIVE) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC_DAC_DMA_CHANNEL);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/dac_lld.c
|
||||
* @brief LPC43xx DAC subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief CHN1 driver identifier.*/
|
||||
DACDriver DACD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static lpc_dma_lli_config_t lpc_dac_lli[2] __attribute__((aligned(0x10)));
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Shared end/half-of-tx service routine.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] flags pre-shifted content of the ISR register
|
||||
*/
|
||||
static void dac_serve_dma_interrupt(DACDriver *dacp, uint32_t flags) {
|
||||
|
||||
if ((flags & (1 << LPC_DAC_DMA_CHANNEL)) != 0) {
|
||||
_dac_isr_error_code(dacp, flags); /* DMA errors handling.*/
|
||||
}
|
||||
else {
|
||||
if (dacp->half_buffer == false) {
|
||||
_dac_isr_half_code(dacp);
|
||||
dacp->half_buffer = true;
|
||||
}
|
||||
else {
|
||||
_dac_isr_full_code(dacp);
|
||||
dacp->half_buffer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level DAC driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_init(void) {
|
||||
dacObjectInit(&DACD1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start(DACDriver *dacp) {
|
||||
|
||||
if (dacp->state == DAC_STOP) {
|
||||
|
||||
LPC_CCU1->CLK_APB3_DAC_CFG = 1; /* Enable clock. */
|
||||
LPC_DAC->CR = 0;
|
||||
LPC_DAC->CTRL = 0;
|
||||
LPC_DAC->CNTVAL = LPC_BASE_APB3_CLK/dacp->config->frequency;
|
||||
|
||||
dmaMuxSet(PERIPHERAL15, 0);
|
||||
dmaChannelAllocate(LPC_DAC_DMA_CHANNEL, \
|
||||
(lpc_dmaisr_t)dac_serve_dma_interrupt, \
|
||||
(void *)dacp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the DAC peripheral.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_stop(DACDriver *dacp) {
|
||||
|
||||
/* If in ready state then disables the DAC clock.*/
|
||||
if (dacp->state == DAC_READY) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC_DAC_DMA_CHANNEL);
|
||||
dmaChannelRelease(LPC_DAC_DMA_CHANNEL);
|
||||
|
||||
LPC_DAC->CTRL = 0; /* Disable DAC */
|
||||
LPC_CCU1->CLK_APB3_DAC_CFG = 0; /* Disable clock. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the DAC bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void dac_lld_start_conversion(DACDriver *dacp) {
|
||||
|
||||
dacp->half_buffer = false;
|
||||
uint32_t dma_ch_config;
|
||||
|
||||
/* DMA configuration */
|
||||
lpc_dac_lli[0].srcaddr = (uint32_t) &dacp->samples[0];
|
||||
lpc_dac_lli[0].dstaddr = (uint32_t)&LPC_DAC->CR;
|
||||
lpc_dac_lli[0].lli = (uint32_t) &lpc_dac_lli[1];
|
||||
lpc_dac_lli[0].control =
|
||||
DMA_CTRL_TRANSFER_SIZE(dacp->depth/2) |
|
||||
DMA_CTRL_SRC_BSIZE_1 |
|
||||
DMA_CTRL_DST_BSIZE_1 |
|
||||
DMA_CTRL_SRC_WIDTH_WORD |
|
||||
DMA_CTRL_DST_WIDTH_WORD |
|
||||
DMA_CTRL_SRC_AHBM0 |
|
||||
DMA_CTRL_DST_AHBM1 |
|
||||
DMA_CTRL_SRC_INC |
|
||||
DMA_CTRL_DST_NOINC |
|
||||
DMA_CTRL_PROT1_USER |
|
||||
DMA_CTRL_PROT2_NONBUFF |
|
||||
DMA_CTRL_PROT3_NONCACHE |
|
||||
DMA_CTRL_INT;
|
||||
|
||||
lpc_dac_lli[1].srcaddr = (uint32_t) &dacp->samples[dacp->depth/2];
|
||||
lpc_dac_lli[1].dstaddr = lpc_dac_lli[0].dstaddr;
|
||||
lpc_dac_lli[1].control = lpc_dac_lli[0].control;
|
||||
|
||||
if (dacp->grpp->circular == true) {
|
||||
lpc_dac_lli[1].lli = (uint32_t) &lpc_dac_lli[0];
|
||||
}
|
||||
else {
|
||||
lpc_dac_lli[1].lli = 0;
|
||||
}
|
||||
|
||||
dma_ch_config =
|
||||
DMA_CFG_CH_ENABLE |
|
||||
DMA_CFG_DST_PERIPH(PERIPHERAL15) |
|
||||
DMA_CFG_FCTRL_M2P |
|
||||
DMA_CFG_IE |
|
||||
DMA_CFG_ITC;
|
||||
|
||||
dmaChannelSrcAddr(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].srcaddr);
|
||||
dmaChannelDstAddr(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].dstaddr);
|
||||
dmaChannelLinkedList(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].lli, DMA_LLI_AHBM0);
|
||||
dmaChannelControl(LPC_DAC_DMA_CHANNEL, lpc_dac_lli[0].control);
|
||||
dmaChannelConfig(LPC_DAC_DMA_CHANNEL, dma_ch_config);
|
||||
|
||||
LPC_DAC->CTRL = DACCTRL_DMA_ENA | DACCTRL_CNT_ENA | DACCTRL_DBLBUF_ENA;
|
||||
}
|
||||
|
||||
void dac_lld_stop_conversion(DACDriver *dacp) {
|
||||
|
||||
/* If in active state then disables the DAC.*/
|
||||
if (dacp->state == DAC_ACTIVE) {
|
||||
|
||||
/* DMA disable.*/
|
||||
dmaChannelDisable(LPC_DAC_DMA_CHANNEL);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,207 +1,207 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/dac_lld.h
|
||||
* @brief LPC43xx DAC subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _DAC_LLD_H_
|
||||
#define _DAC_LLD_H_
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DACR_BIAS (1UL << 16)
|
||||
|
||||
#define DACCTRL_INT_DMA_REQ (1UL << 0)
|
||||
#define DACCTRL_DBLBUF_ENA (1UL << 1)
|
||||
#define DACCTRL_CNT_ENA (1UL << 2)
|
||||
#define DACCTRL_DMA_ENA (1UL << 3)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA stream used for DAC CHN1 TX operations.
|
||||
* @note This option is only available on platforms with enhanced DMA.
|
||||
*/
|
||||
#if !defined(LPC_DAC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC_DAC_DMA_CHANNEL DMA_CHANNEL5
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(LPC_DMA_REQUIRED)
|
||||
#define LPC_DMA_REQUIRED
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct DACDriver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type representing a DAC sample.
|
||||
*/
|
||||
typedef uint32_t dacsample_t;
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacendcallback_t)(DACDriver *dacp, const dacsample_t * samples, size_t pos);
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacerrcallback_t)(DACDriver *dacp, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint16_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
dacendcallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrcallback_t error_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
bool circular;
|
||||
|
||||
} DACConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer frequency in Hz.
|
||||
*/
|
||||
uint32_t frequency;
|
||||
/* End of the mandatory fields.*/
|
||||
} DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct DACDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
const dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
uint16_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if DAC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* DAC_USE_WAIT */
|
||||
#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern DACDriver DACD1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dac_lld_init(void);
|
||||
void dac_lld_start(DACDriver *dacp);
|
||||
void dac_lld_stop(DACDriver *dacp);
|
||||
void dac_lld_start_conversion(DACDriver *dacp);
|
||||
void dac_lld_stop_conversion(DACDriver *dacp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
#endif /* _DAC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DAC driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/dac_lld.h
|
||||
* @brief LPC43xx DAC subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _DAC_LLD_H_
|
||||
#define _DAC_LLD_H_
|
||||
|
||||
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define DACR_BIAS (1UL << 16)
|
||||
|
||||
#define DACCTRL_INT_DMA_REQ (1UL << 0)
|
||||
#define DACCTRL_DBLBUF_ENA (1UL << 1)
|
||||
#define DACCTRL_CNT_ENA (1UL << 2)
|
||||
#define DACCTRL_DMA_ENA (1UL << 3)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA stream used for DAC CHN1 TX operations.
|
||||
* @note This option is only available on platforms with enhanced DMA.
|
||||
*/
|
||||
#if !defined(LPC_DAC_DMA_CHANNEL) || defined(__DOXYGEN__)
|
||||
#define LPC_DAC_DMA_CHANNEL DMA_CHANNEL5
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(LPC_DMA_REQUIRED)
|
||||
#define LPC_DMA_REQUIRED
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an DAC driver.
|
||||
*/
|
||||
typedef struct DACDriver DACDriver;
|
||||
|
||||
/**
|
||||
* @brief Type representing a DAC sample.
|
||||
*/
|
||||
typedef uint32_t dacsample_t;
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacendcallback_t)(DACDriver *dacp, const dacsample_t * samples, size_t pos);
|
||||
|
||||
/**
|
||||
* @brief DAC notification callback type.
|
||||
*
|
||||
* @param[in] dacp pointer to the @p DACDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*dacerrcallback_t)(DACDriver *dacp, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief DAC Conversion group structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Number of DAC channels.
|
||||
*/
|
||||
uint16_t num_channels;
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
dacendcallback_t end_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
dacerrcallback_t error_cb;
|
||||
/**
|
||||
* @brief Error handling callback or @p NULL.
|
||||
*/
|
||||
bool circular;
|
||||
|
||||
} DACConversionGroup;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer frequency in Hz.
|
||||
*/
|
||||
uint32_t frequency;
|
||||
/* End of the mandatory fields.*/
|
||||
} DACConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a DAC driver.
|
||||
*/
|
||||
struct DACDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
dacstate_t state;
|
||||
/**
|
||||
* @brief Conversion group.
|
||||
*/
|
||||
const DACConversionGroup *grpp;
|
||||
/**
|
||||
* @brief Samples buffer pointer.
|
||||
*/
|
||||
const dacsample_t *samples;
|
||||
/**
|
||||
* @brief Samples buffer size.
|
||||
*/
|
||||
uint16_t depth;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const DACConfig *config;
|
||||
#if DAC_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* DAC_USE_WAIT */
|
||||
#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(DAC_DRIVER_EXT_FIELDS)
|
||||
DAC_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Half buffer indicator.
|
||||
*/
|
||||
bool_t half_buffer;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern DACDriver DACD1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dac_lld_init(void);
|
||||
void dac_lld_start(DACDriver *dacp);
|
||||
void dac_lld_stop(DACDriver *dacp);
|
||||
void dac_lld_start_conversion(DACDriver *dacp);
|
||||
void dac_lld_stop_conversion(DACDriver *dacp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_DAC */
|
||||
|
||||
#endif /* _DAC_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,338 +1,338 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/gpt_lld.c
|
||||
* @brief LPC43xx GPT subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver identifier.
|
||||
* @note The driver GPT1 allocates the complex timer TIM0 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM0 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver identifier.
|
||||
* @note The driver GPT2 allocates the timer TIM1 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM1 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver identifier.
|
||||
* @note The driver GPT3 allocates the timer TIM2 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM2 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver identifier.
|
||||
* @note The driver GPT4 allocates the timer TIM3 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM3 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Shared IRQ handler.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
*/
|
||||
static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/
|
||||
if (gptp->state == GPT_ONESHOT) {
|
||||
gptp->state = GPT_READY; /* Back in GPT_READY state. */
|
||||
gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
|
||||
}
|
||||
gptp->config->callback(gptp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
/**
|
||||
* @brief TIM0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector70) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC_GPT_USE_TIM1
|
||||
/**
|
||||
* @brief TIM1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector74) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC_GPT_USE_TIM2
|
||||
/**
|
||||
* @brief TIM2 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector78) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM2 */
|
||||
|
||||
#if LPC_GPT_USE_TIM3
|
||||
/**
|
||||
* @brief TIM3 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector7C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM3 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level GPT driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_init(void) {
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
/* Driver initialization.*/
|
||||
GPTD1.tmr = LPC_TIMER0;
|
||||
gptObjectInit(&GPTD1);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM1
|
||||
/* Driver initialization.*/
|
||||
GPTD2.tmr = LPC_TIMER1;
|
||||
gptObjectInit(&GPTD2);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM2
|
||||
/* Driver initialization.*/
|
||||
GPTD3.tmr = LPC_TIMER2;
|
||||
gptObjectInit(&GPTD3);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM3
|
||||
/* Driver initialization.*/
|
||||
GPTD4.tmr = LPC_TIMER3;
|
||||
gptObjectInit(&GPTD4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start(GPTDriver *gptp) {
|
||||
uint32_t pr;
|
||||
|
||||
if (gptp->state == GPT_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG = 1;
|
||||
nvicEnableVector(TIMER0_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG = 1;
|
||||
nvicEnableVector(TIMER1_IRQn, CORTEX_PRIORITY_MASK(3));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG = 1;
|
||||
nvicEnableVector(TIMER2_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG = 1;
|
||||
nvicEnableVector(TIMER3_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prescaler value calculation.*/
|
||||
pr = (uint16_t)((LPC_BASE_M4_CLK/ gptp->config->frequency) - 1);
|
||||
chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC_BASE_M4_CLK,
|
||||
"gpt_lld_start(), #1", "invalid frequency");
|
||||
|
||||
/* Timer configuration.*/
|
||||
gptp->tmr->PR = pr;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop(GPTDriver *gptp) {
|
||||
|
||||
if (gptp->state == GPT_READY) {
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
nvicDisableVector(TIMER0_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
nvicDisableVector(TIMER1_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
nvicDisableVector(TIMER2_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
nvicDisableVector(TIMER3_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in continuous mode.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval period in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR[0] = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in one shot mode and waits for completion.
|
||||
* @details This function specifically polls the timer waiting for completion
|
||||
* in order to not have extra delays caused by interrupt servicing,
|
||||
* this function is only recommended for short delays.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval time interval in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR[0] = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 4; /* Stop TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
while (gptp->tmr->TCR & 1)
|
||||
;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/gpt_lld.c
|
||||
* @brief LPC43xx GPT subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver identifier.
|
||||
* @note The driver GPT1 allocates the complex timer TIM0 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM0 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver identifier.
|
||||
* @note The driver GPT2 allocates the timer TIM1 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM1 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver identifier.
|
||||
* @note The driver GPT3 allocates the timer TIM2 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM2 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver identifier.
|
||||
* @note The driver GPT4 allocates the timer TIM3 when enabled.
|
||||
*/
|
||||
#if LPC_GPT_USE_TIM3 || defined(__DOXYGEN__)
|
||||
GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Shared IRQ handler.
|
||||
*
|
||||
* @param[in] gptp pointer to a @p GPTDriver object
|
||||
*/
|
||||
static void gpt_lld_serve_interrupt(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1; /* Clear interrupt on match MR0.*/
|
||||
if (gptp->state == GPT_ONESHOT) {
|
||||
gptp->state = GPT_READY; /* Back in GPT_READY state. */
|
||||
gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */
|
||||
}
|
||||
gptp->config->callback(gptp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
/**
|
||||
* @brief TIM0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector70) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC_GPT_USE_TIM1
|
||||
/**
|
||||
* @brief TIM1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector74) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM0 */
|
||||
|
||||
#if LPC_GPT_USE_TIM2
|
||||
/**
|
||||
* @brief TIM2 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector78) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM2 */
|
||||
|
||||
#if LPC_GPT_USE_TIM3
|
||||
/**
|
||||
* @brief TIM3 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector7C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
gpt_lld_serve_interrupt(&GPTD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif /* LPC_GPT_USE_TIM3 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level GPT driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_init(void) {
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
/* Driver initialization.*/
|
||||
GPTD1.tmr = LPC_TIMER0;
|
||||
gptObjectInit(&GPTD1);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM1
|
||||
/* Driver initialization.*/
|
||||
GPTD2.tmr = LPC_TIMER1;
|
||||
gptObjectInit(&GPTD2);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM2
|
||||
/* Driver initialization.*/
|
||||
GPTD3.tmr = LPC_TIMER2;
|
||||
gptObjectInit(&GPTD3);
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM3
|
||||
/* Driver initialization.*/
|
||||
GPTD4.tmr = LPC_TIMER3;
|
||||
gptObjectInit(&GPTD4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start(GPTDriver *gptp) {
|
||||
uint32_t pr;
|
||||
|
||||
if (gptp->state == GPT_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG = 1;
|
||||
nvicEnableVector(TIMER0_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG = 1;
|
||||
nvicEnableVector(TIMER1_IRQn, CORTEX_PRIORITY_MASK(3));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG = 1;
|
||||
nvicEnableVector(TIMER2_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG = 1;
|
||||
nvicEnableVector(TIMER3_IRQn, CORTEX_PRIORITY_MASK(2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prescaler value calculation.*/
|
||||
pr = (uint16_t)((LPC_BASE_M4_CLK/ gptp->config->frequency) - 1);
|
||||
chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC_BASE_M4_CLK,
|
||||
"gpt_lld_start(), #1", "invalid frequency");
|
||||
|
||||
/* Timer configuration.*/
|
||||
gptp->tmr->PR = pr;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the GPT peripheral.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop(GPTDriver *gptp) {
|
||||
|
||||
if (gptp->state == GPT_READY) {
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
|
||||
#if LPC_GPT_USE_TIM0
|
||||
if (&GPTD1 == gptp) {
|
||||
nvicDisableVector(TIMER0_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM1
|
||||
if (&GPTD2 == gptp) {
|
||||
nvicDisableVector(TIMER1_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM2
|
||||
if (&GPTD3 == gptp) {
|
||||
nvicDisableVector(TIMER2_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
#if LPC_GPT_USE_TIM3
|
||||
if (&GPTD4 == gptp) {
|
||||
nvicDisableVector(TIMER3_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in continuous mode.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval period in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR[0] = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 3; /* IRQ and clr TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the timer.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp) {
|
||||
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the timer in one shot mode and waits for completion.
|
||||
* @details This function specifically polls the timer waiting for completion
|
||||
* in order to not have extra delays caused by interrupt servicing,
|
||||
* this function is only recommended for short delays.
|
||||
*
|
||||
* @param[in] gptp pointer to the @p GPTDriver object
|
||||
* @param[in] interval time interval in ticks
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
|
||||
|
||||
gptp->tmr->MR[0] = interval - 1;
|
||||
gptp->tmr->IR = 1;
|
||||
gptp->tmr->MCR = 4; /* Stop TC on match MR0. */
|
||||
gptp->tmr->TCR = 2; /* Reset counter and prescaler. */
|
||||
gptp->tmr->TCR = 1; /* Timer enabled. */
|
||||
while (gptp->tmr->TCR & 1)
|
||||
;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,208 +1,208 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/gpt_lld.h
|
||||
* @brief LPC43xx GPT subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GPT_LLD_H_
|
||||
#define _GPT_LLD_H_
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM0) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM1) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM2) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT4 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM3) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM0_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM1_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM2_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM3_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC_GPT_USE_TIM0 && !LPC_GPT_USE_TIM1 && \
|
||||
!LPC_GPT_USE_TIM2 && !LPC_GPT_USE_TIM3
|
||||
#error "GPT driver activated but no CT peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
typedef uint32_t gptfreq_t;
|
||||
|
||||
/**
|
||||
* @brief GPT counter type.
|
||||
*/
|
||||
typedef uint32_t gptcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer clock in Hz.
|
||||
* @note The low level can use assertions in order to catch invalid
|
||||
* frequency specifications.
|
||||
*/
|
||||
gptfreq_t frequency;
|
||||
/**
|
||||
* @brief Timer callback pointer.
|
||||
* @note This callback is invoked on GPT counter events.
|
||||
*/
|
||||
gptcallback_t callback;
|
||||
/* End of the mandatory fields.*/
|
||||
} GPTConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT driver.
|
||||
*/
|
||||
struct GPTDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
gptstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const GPTConfig *config;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Timer base clock.
|
||||
*/
|
||||
uint32_t clock;
|
||||
/**
|
||||
* @brief Pointer to the LPC_TIMERx registers block.
|
||||
*/
|
||||
LPC_TIMERn_Type *tmr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_GPT_USE_TIM0 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM1 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM2 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM3 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void gpt_lld_init(void);
|
||||
void gpt_lld_start(GPTDriver *gptp);
|
||||
void gpt_lld_stop(GPTDriver *gptp);
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp);
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
#endif /* _GPT_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/gpt_lld.h
|
||||
* @brief LPC43xx GPT subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup GPT
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GPT_LLD_H_
|
||||
#define _GPT_LLD_H_
|
||||
|
||||
#if HAL_USE_GPT || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM0) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT2 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM1) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT3 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM2) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 driver enable switch.
|
||||
* @details If set to @p TRUE the support for GPT4 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_GPT_USE_TIM3) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_USE_TIM3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM0_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM1_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM2_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPT4 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_GPT_TIM3_IRQ_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC_GPT_USE_TIM0 && !LPC_GPT_USE_TIM1 && \
|
||||
!LPC_GPT_USE_TIM2 && !LPC_GPT_USE_TIM3
|
||||
#error "GPT driver activated but no CT peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
typedef uint32_t gptfreq_t;
|
||||
|
||||
/**
|
||||
* @brief GPT counter type.
|
||||
*/
|
||||
typedef uint32_t gptcnt_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note It could be empty on some architectures.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Timer clock in Hz.
|
||||
* @note The low level can use assertions in order to catch invalid
|
||||
* frequency specifications.
|
||||
*/
|
||||
gptfreq_t frequency;
|
||||
/**
|
||||
* @brief Timer callback pointer.
|
||||
* @note This callback is invoked on GPT counter events.
|
||||
*/
|
||||
gptcallback_t callback;
|
||||
/* End of the mandatory fields.*/
|
||||
} GPTConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT driver.
|
||||
*/
|
||||
struct GPTDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
gptstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const GPTConfig *config;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Timer base clock.
|
||||
*/
|
||||
uint32_t clock;
|
||||
/**
|
||||
* @brief Pointer to the LPC_TIMERx registers block.
|
||||
*/
|
||||
LPC_TIMERn_Type *tmr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_GPT_USE_TIM0 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD1;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM1 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD2;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM2 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD3;
|
||||
#endif
|
||||
|
||||
#if LPC_GPT_USE_TIM3 && !defined(__DOXYGEN__)
|
||||
extern GPTDriver GPTD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void gpt_lld_init(void);
|
||||
void gpt_lld_start(GPTDriver *gptp);
|
||||
void gpt_lld_stop(GPTDriver *gptp);
|
||||
void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
|
||||
void gpt_lld_stop_timer(GPTDriver *gptp);
|
||||
void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_GPT */
|
||||
|
||||
#endif /* _GPT_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,194 +1,194 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/hal_lld.c
|
||||
* @brief LPC43xx HAL subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/**
|
||||
* @brief Register missing in NXP header file.
|
||||
*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define LPC_IDIV_ARRAY_NUM 5
|
||||
#define LPC_BASE_CLK_ARRAY_NUM 27
|
||||
|
||||
const uint32_t lpc_idiv[LPC_IDIV_ARRAY_NUM] = {
|
||||
(((uint32_t)LPC_IDIVA_SRC) << 24) | (LPC_IDIVA_DIV << 2) | (!LPC_IDIVA_ENABLE),
|
||||
(((uint32_t)LPC_IDIVB_SRC) << 24) | (LPC_IDIVB_DIV << 2) | (!LPC_IDIVB_ENABLE),
|
||||
(((uint32_t)LPC_IDIVC_SRC) << 24) | (LPC_IDIVC_DIV << 2) | (!LPC_IDIVC_ENABLE),
|
||||
(((uint32_t)LPC_IDIVD_SRC) << 24) | (LPC_IDIVD_DIV << 2) | (!LPC_IDIVD_ENABLE),
|
||||
(((uint32_t)LPC_IDIVE_SRC) << 24) | (LPC_IDIVE_DIV << 2) | (!LPC_IDIVE_ENABLE)
|
||||
};
|
||||
|
||||
const uint32_t lpc_base_clk[LPC_BASE_CLK_ARRAY_NUM] = {
|
||||
(CLK_SEL_PLL0USB << 24) | (!LPC_BASE_USB0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PERIPH_CLK_SRC) << 24) | (!LPC_BASE_PERIPH_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_USB1_CLK_SRC) << 24) | (!LPC_BASE_USB1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_M4_CLK_SRC) << 24) | (!LPC_BASE_M4_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SPIFI_CLK_SRC) << 24) | (!LPC_BASE_SPIFI_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SPI_CLK_SRC) << 24) | (!LPC_BASE_SPI_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PHY_RX_CLK_SRC) << 24) | (!LPC_BASE_PHY_RX_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PHY_TX_CLK_SRC) << 24) | (!LPC_BASE_PHY_TX_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_APB1_CLK_SRC) << 24) | (!LPC_BASE_APB1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_APB3_CLK_SRC) << 24) | (!LPC_BASE_APB3_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_LCD_CLK_SRC) << 24) | (!LPC_BASE_LCD_CLK_ENABLE),
|
||||
0,
|
||||
(((uint32_t)LPC_BASE_SDIO_CLK_SRC) << 24) | (!LPC_BASE_SDIO_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SSP0_CLK_SRC) << 24) | (!LPC_BASE_SSP0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SSP1_CLK_SRC) << 24) | (!LPC_BASE_SSP1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART0_CLK_SRC) << 24) | (!LPC_BASE_UART0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART1_CLK_SRC) << 24) | (!LPC_BASE_UART1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART2_CLK_SRC) << 24) | (!LPC_BASE_UART2_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART3_CLK_SRC) << 24) | (!LPC_BASE_UART3_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_OUT_CLK_SRC) << 24) | (!LPC_BASE_OUT_CLK_ENABLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(((uint32_t)LPC_BASE_APLL_CLK_SRC) << 24) | (!LPC_BASE_APLL_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_CGU_OUT0_CLK_SRC) << 24) | (!LPC_BASE_CGU_OUT0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_CGU_OUT1_CLK_SRC) << 24) | (!LPC_BASE_CGU_OUT1_CLK_ENABLE)
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level HAL driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void hal_lld_init(void) {
|
||||
|
||||
/* SysTick initialization using the system clock.*/
|
||||
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, CORTEX_PRIORITY_SYSTICK);
|
||||
SysTick->LOAD = LPC_BASE_M4_CLK / CH_FREQUENCY - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk;
|
||||
|
||||
/* DWT cycle counter enable.*/
|
||||
SCS_DEMCR |= SCS_DEMCR_TRCENA;
|
||||
DWT_CTRL |= DWT_CTRL_CYCCNTENA;
|
||||
|
||||
#if defined(LPC_DMA_REQUIRED)
|
||||
dmaInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LPC43xx clocks and PLL initialization.
|
||||
* @note All the involved constants come from the file @p board.h.
|
||||
* @note This function must be invoked only after the system reset.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void lpc_clock_init(void) {
|
||||
|
||||
uint32_t i;
|
||||
volatile uint32_t * preg;
|
||||
|
||||
#if !LPC_FLASHLESS
|
||||
/* Flash wait states setting.*/
|
||||
preg = (volatile uint32_t *) 0x40043120; /* FLASHCFGA */
|
||||
*preg = (1UL<< 31) | (LPC_FLASHCFG_FLASHTIM << 12) | 0x3A;
|
||||
*(preg + 1)= (1UL<< 31) | (LPC_FLASHCFG_FLASHTIM << 12) | 0x3A; /* FLASHCFGB 0x40043124 */
|
||||
#endif
|
||||
|
||||
/* System oscillator initialization if required.*/
|
||||
#if LPC_XTAL_ENABLE
|
||||
LPC_CGU->XTAL_OSC_CTRL = (LPC_OSCRANGE << 2); /* Enable Main oscillator */
|
||||
for(i = 0; i < 1000000; i++)
|
||||
; /* Wait for main oscillator to be ready */
|
||||
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_XTAL << 24); /* Select the crystal oscillator */
|
||||
/* as clock source for BASE_M4_CLK */
|
||||
#else
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_IRC << 24); /* Select IRC as clock source for BASE_M4_CLK */
|
||||
#endif
|
||||
|
||||
LPC_CGU->PLL1_CTRL = 0; /* Power-down PLL1 enabled by Boot ROM */
|
||||
|
||||
#if LPC_PLL1_ENABLE /* PLL1 works in direct or non-integer mode. */
|
||||
/* Set PLL1 to FCLKOUT/2 */
|
||||
LPC_CGU->PLL1_CTRL = (1UL << 24) | (LPC_PLL1_CTRL_MSEL << 16) |
|
||||
(LPC_PLL1_CTRL_NSEL << 12);
|
||||
|
||||
while (!(LPC_CGU->PLL1_STAT & 0x01))
|
||||
; /* Wait for PLL1 locked */
|
||||
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_PLL1 << 24); /* Select PPL1 clock as source for BASE_M4_CLK. */
|
||||
|
||||
for(i = 0; i < 200000; i++)
|
||||
; /* Wait */
|
||||
|
||||
#if LPC_PLL1_POSTDIV_ENABLE
|
||||
LPC_CGU->PLL1_CTRL |= (LPC_PLL1_CTRL_PSEL << 8);
|
||||
#else
|
||||
LPC_CGU->PLL1_CTRL |= (1UL << 7); /* Set PLL1 to FCLKOUT > 156 MHz*/
|
||||
#endif
|
||||
#endif /* LPC_PLL1_ENABLE == TRUE */
|
||||
|
||||
/* Config integer dividers. */
|
||||
preg = &LPC_CGU->IDIVA_CTRL;
|
||||
for (i = 0; i < LPC_IDIV_ARRAY_NUM; i++) {
|
||||
*preg = lpc_idiv[i];
|
||||
preg++;
|
||||
}
|
||||
|
||||
/* Config base clocks. */
|
||||
preg = &LPC_CGU->BASE_USB0_CLK;
|
||||
for (i = 0; i < LPC_BASE_CLK_ARRAY_NUM; i++) {
|
||||
*preg = lpc_base_clk[i];
|
||||
preg++;
|
||||
}
|
||||
|
||||
#if LPC_PLL0USB0_ENABLE
|
||||
#error "PPL0USB0 not supported."
|
||||
#endif /* LPC_PLL0USB_ENABLE == TRUE */
|
||||
|
||||
#if LPC_PLL0AUDIO_ENABLE
|
||||
#error "PLL0AUDIO not supported."
|
||||
#endif /* LPC_PLL0AUDIO == TRUE */
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx HAL driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/hal_lld.c
|
||||
* @brief LPC43xx HAL subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/**
|
||||
* @brief Register missing in NXP header file.
|
||||
*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define LPC_IDIV_ARRAY_NUM 5
|
||||
#define LPC_BASE_CLK_ARRAY_NUM 27
|
||||
|
||||
const uint32_t lpc_idiv[LPC_IDIV_ARRAY_NUM] = {
|
||||
(((uint32_t)LPC_IDIVA_SRC) << 24) | (LPC_IDIVA_DIV << 2) | (!LPC_IDIVA_ENABLE),
|
||||
(((uint32_t)LPC_IDIVB_SRC) << 24) | (LPC_IDIVB_DIV << 2) | (!LPC_IDIVB_ENABLE),
|
||||
(((uint32_t)LPC_IDIVC_SRC) << 24) | (LPC_IDIVC_DIV << 2) | (!LPC_IDIVC_ENABLE),
|
||||
(((uint32_t)LPC_IDIVD_SRC) << 24) | (LPC_IDIVD_DIV << 2) | (!LPC_IDIVD_ENABLE),
|
||||
(((uint32_t)LPC_IDIVE_SRC) << 24) | (LPC_IDIVE_DIV << 2) | (!LPC_IDIVE_ENABLE)
|
||||
};
|
||||
|
||||
const uint32_t lpc_base_clk[LPC_BASE_CLK_ARRAY_NUM] = {
|
||||
(CLK_SEL_PLL0USB << 24) | (!LPC_BASE_USB0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PERIPH_CLK_SRC) << 24) | (!LPC_BASE_PERIPH_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_USB1_CLK_SRC) << 24) | (!LPC_BASE_USB1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_M4_CLK_SRC) << 24) | (!LPC_BASE_M4_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SPIFI_CLK_SRC) << 24) | (!LPC_BASE_SPIFI_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SPI_CLK_SRC) << 24) | (!LPC_BASE_SPI_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PHY_RX_CLK_SRC) << 24) | (!LPC_BASE_PHY_RX_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_PHY_TX_CLK_SRC) << 24) | (!LPC_BASE_PHY_TX_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_APB1_CLK_SRC) << 24) | (!LPC_BASE_APB1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_APB3_CLK_SRC) << 24) | (!LPC_BASE_APB3_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_LCD_CLK_SRC) << 24) | (!LPC_BASE_LCD_CLK_ENABLE),
|
||||
0,
|
||||
(((uint32_t)LPC_BASE_SDIO_CLK_SRC) << 24) | (!LPC_BASE_SDIO_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SSP0_CLK_SRC) << 24) | (!LPC_BASE_SSP0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_SSP1_CLK_SRC) << 24) | (!LPC_BASE_SSP1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART0_CLK_SRC) << 24) | (!LPC_BASE_UART0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART1_CLK_SRC) << 24) | (!LPC_BASE_UART1_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART2_CLK_SRC) << 24) | (!LPC_BASE_UART2_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_UART3_CLK_SRC) << 24) | (!LPC_BASE_UART3_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_OUT_CLK_SRC) << 24) | (!LPC_BASE_OUT_CLK_ENABLE),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(((uint32_t)LPC_BASE_APLL_CLK_SRC) << 24) | (!LPC_BASE_APLL_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_CGU_OUT0_CLK_SRC) << 24) | (!LPC_BASE_CGU_OUT0_CLK_ENABLE),
|
||||
(((uint32_t)LPC_BASE_CGU_OUT1_CLK_SRC) << 24) | (!LPC_BASE_CGU_OUT1_CLK_ENABLE)
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level HAL driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void hal_lld_init(void) {
|
||||
|
||||
/* SysTick initialization using the system clock.*/
|
||||
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, CORTEX_PRIORITY_SYSTICK);
|
||||
SysTick->LOAD = LPC_BASE_M4_CLK / CH_FREQUENCY - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
|
||||
SysTick_CTRL_ENABLE_Msk |
|
||||
SysTick_CTRL_TICKINT_Msk;
|
||||
|
||||
/* DWT cycle counter enable.*/
|
||||
SCS_DEMCR |= SCS_DEMCR_TRCENA;
|
||||
DWT_CTRL |= DWT_CTRL_CYCCNTENA;
|
||||
|
||||
#if defined(LPC_DMA_REQUIRED)
|
||||
dmaInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief LPC43xx clocks and PLL initialization.
|
||||
* @note All the involved constants come from the file @p board.h.
|
||||
* @note This function must be invoked only after the system reset.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void lpc_clock_init(void) {
|
||||
|
||||
uint32_t i;
|
||||
volatile uint32_t * preg;
|
||||
|
||||
#if !LPC_FLASHLESS
|
||||
/* Flash wait states setting.*/
|
||||
preg = (volatile uint32_t *) 0x40043120; /* FLASHCFGA */
|
||||
*preg = (1UL<< 31) | (LPC_FLASHCFG_FLASHTIM << 12) | 0x3A;
|
||||
*(preg + 1)= (1UL<< 31) | (LPC_FLASHCFG_FLASHTIM << 12) | 0x3A; /* FLASHCFGB 0x40043124 */
|
||||
#endif
|
||||
|
||||
/* System oscillator initialization if required.*/
|
||||
#if LPC_XTAL_ENABLE
|
||||
LPC_CGU->XTAL_OSC_CTRL = (LPC_OSCRANGE << 2); /* Enable Main oscillator */
|
||||
for(i = 0; i < 1000000; i++)
|
||||
; /* Wait for main oscillator to be ready */
|
||||
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_XTAL << 24); /* Select the crystal oscillator */
|
||||
/* as clock source for BASE_M4_CLK */
|
||||
#else
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_IRC << 24); /* Select IRC as clock source for BASE_M4_CLK */
|
||||
#endif
|
||||
|
||||
LPC_CGU->PLL1_CTRL = 0; /* Power-down PLL1 enabled by Boot ROM */
|
||||
|
||||
#if LPC_PLL1_ENABLE /* PLL1 works in direct or non-integer mode. */
|
||||
/* Set PLL1 to FCLKOUT/2 */
|
||||
LPC_CGU->PLL1_CTRL = (1UL << 24) | (LPC_PLL1_CTRL_MSEL << 16) |
|
||||
(LPC_PLL1_CTRL_NSEL << 12);
|
||||
|
||||
while (!(LPC_CGU->PLL1_STAT & 0x01))
|
||||
; /* Wait for PLL1 locked */
|
||||
|
||||
LPC_CGU->BASE_M4_CLK = (CLK_SEL_PLL1 << 24); /* Select PPL1 clock as source for BASE_M4_CLK. */
|
||||
|
||||
for(i = 0; i < 200000; i++)
|
||||
; /* Wait */
|
||||
|
||||
#if LPC_PLL1_POSTDIV_ENABLE
|
||||
LPC_CGU->PLL1_CTRL |= (LPC_PLL1_CTRL_PSEL << 8);
|
||||
#else
|
||||
LPC_CGU->PLL1_CTRL |= (1UL << 7); /* Set PLL1 to FCLKOUT > 156 MHz*/
|
||||
#endif
|
||||
#endif /* LPC_PLL1_ENABLE == TRUE */
|
||||
|
||||
/* Config integer dividers. */
|
||||
preg = &LPC_CGU->IDIVA_CTRL;
|
||||
for (i = 0; i < LPC_IDIV_ARRAY_NUM; i++) {
|
||||
*preg = lpc_idiv[i];
|
||||
preg++;
|
||||
}
|
||||
|
||||
/* Config base clocks. */
|
||||
preg = &LPC_CGU->BASE_USB0_CLK;
|
||||
for (i = 0; i < LPC_BASE_CLK_ARRAY_NUM; i++) {
|
||||
*preg = lpc_base_clk[i];
|
||||
preg++;
|
||||
}
|
||||
|
||||
#if LPC_PLL0USB0_ENABLE
|
||||
#error "PPL0USB0 not supported."
|
||||
#endif /* LPC_PLL0USB_ENABLE == TRUE */
|
||||
|
||||
#if LPC_PLL0AUDIO_ENABLE
|
||||
#error "PLL0AUDIO not supported."
|
||||
#endif /* LPC_PLL0AUDIO == TRUE */
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,201 +1,201 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/LPC43xx_dma.c
|
||||
* @brief DMA driver code.
|
||||
*
|
||||
* @addtogroup LPC43xx_DMA
|
||||
* @details DMA sharing helper driver. In the LPC43xx the DMA streams are a
|
||||
* shared resource, this driver allows to allocate and free DMA
|
||||
* streams at runtime in order to allow all the other device
|
||||
* drivers to coordinate the access to the resource.
|
||||
* @note The DMA ISR handlers are all declared into this module because
|
||||
* sharing, the various device drivers can associate a callback to
|
||||
* ISRs when allocating streams.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/* The following macro is only defined if some driver requiring DMA services
|
||||
has been enabled.*/
|
||||
#if defined(LPC_DMA_REQUIRED) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
lpc_dma_channel_config_t * \
|
||||
_lpc_dma_channel_config[LPC_DMA_CHANNELS] = {
|
||||
LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4,
|
||||
LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7 };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA ISR redirector type.
|
||||
*/
|
||||
typedef struct {
|
||||
lpc_dmaisr_t dma_func; /**< @brief DMA callback function. */
|
||||
void *dma_param; /**< @brief DMA callback parameter. */
|
||||
} dma_isr_redir_t;
|
||||
|
||||
/**
|
||||
* @brief Mask of the allocated streams.
|
||||
*/
|
||||
static uint32_t dma_streams_mask;
|
||||
|
||||
/**
|
||||
* @brief DMA IRQ redirectors.
|
||||
*/
|
||||
static dma_isr_redir_t dma_isr_redir[LPC_DMA_CHANNELS];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector48) {
|
||||
uint32_t irq_status;
|
||||
uint32_t err_status;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
irq_status = LPC_GPDMA->INTTCSTAT;
|
||||
LPC_GPDMA->INTTCCLEAR = irq_status; /* Clear DMA interrupt flag. */
|
||||
err_status = LPC_GPDMA->INTERRSTAT;
|
||||
LPC_GPDMA->INTERRCLR = err_status; /* Clear DMA error flag if any. */
|
||||
|
||||
for (i = 0; i < LPC_DMA_CHANNELS; i++) {
|
||||
if (irq_status & (1UL << i)) {
|
||||
if (dma_isr_redir[i].dma_func)
|
||||
dma_isr_redir[i].dma_func(dma_isr_redir[i].dma_param, err_status);
|
||||
}
|
||||
}
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC43xx DMA initialization.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dmaInit(void) {
|
||||
uint8_t i;
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < LPC_DMA_CHANNELS; i++)
|
||||
_lpc_dma_channel_config[i]->config = 0;
|
||||
|
||||
LPC_GPDMA->INTTCCLEAR = 0xFF;
|
||||
LPC_GPDMA->INTERRCLR = 0xFF;
|
||||
|
||||
LPC_GPDMA->CONFIG = DMACCONFIG_E; /* Enable DMA Controller, little-endian mode */
|
||||
while((LPC_GPDMA->CONFIG & DMACCONFIG_E) != 0x01)
|
||||
;
|
||||
|
||||
nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC_DMA_IRQ_PRIORITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated.
|
||||
* @pre The channel must not be already in use or an error is returned.
|
||||
* @post The channel is allocated and the default ISR handler redirected
|
||||
* to the specified function.
|
||||
* @post The channel must be freed using @p dmaChannelRelease() before it can
|
||||
* be reused with another peripheral.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return The operation status.
|
||||
* @retval FALSE no error, stream taken.
|
||||
* @retval TRUE error, stream already taken.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
bool_t dmaChannelAllocate(lpc_dma_channel_t dmach,
|
||||
lpc_dmaisr_t func,
|
||||
void *param) {
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Checks if the channel is already taken.*/
|
||||
if ((dma_streams_mask & channel) != 0)
|
||||
return TRUE;
|
||||
|
||||
/* Marks the stream as allocated.*/
|
||||
dma_isr_redir[dmach].dma_func = func;
|
||||
dma_isr_redir[dmach].dma_param = param;
|
||||
dma_streams_mask |= channel;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post The channel is again available.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void dmaChannelRelease(lpc_dma_channel_t dmach) {
|
||||
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Check if the streams is not taken.*/
|
||||
chDbgAssert((dma_streams_mask & channel) != 0,
|
||||
"dmaStreamRelease(), #1", "not allocated");
|
||||
|
||||
dma_streams_mask &= ~channel; /* Marks the stream as not allocated.*/
|
||||
}
|
||||
|
||||
#endif /* LPC_DMA_REQUIRED */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/LPC43xx_dma.c
|
||||
* @brief DMA driver code.
|
||||
*
|
||||
* @addtogroup LPC43xx_DMA
|
||||
* @details DMA sharing helper driver. In the LPC43xx the DMA streams are a
|
||||
* shared resource, this driver allows to allocate and free DMA
|
||||
* streams at runtime in order to allow all the other device
|
||||
* drivers to coordinate the access to the resource.
|
||||
* @note The DMA ISR handlers are all declared into this module because
|
||||
* sharing, the various device drivers can associate a callback to
|
||||
* ISRs when allocating streams.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/* The following macro is only defined if some driver requiring DMA services
|
||||
has been enabled.*/
|
||||
#if defined(LPC_DMA_REQUIRED) || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
lpc_dma_channel_config_t * \
|
||||
_lpc_dma_channel_config[LPC_DMA_CHANNELS] = {
|
||||
LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4,
|
||||
LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7 };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA ISR redirector type.
|
||||
*/
|
||||
typedef struct {
|
||||
lpc_dmaisr_t dma_func; /**< @brief DMA callback function. */
|
||||
void *dma_param; /**< @brief DMA callback parameter. */
|
||||
} dma_isr_redir_t;
|
||||
|
||||
/**
|
||||
* @brief Mask of the allocated streams.
|
||||
*/
|
||||
static uint32_t dma_streams_mask;
|
||||
|
||||
/**
|
||||
* @brief DMA IRQ redirectors.
|
||||
*/
|
||||
static dma_isr_redir_t dma_isr_redir[LPC_DMA_CHANNELS];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector48) {
|
||||
uint32_t irq_status;
|
||||
uint32_t err_status;
|
||||
uint8_t i;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
irq_status = LPC_GPDMA->INTTCSTAT;
|
||||
LPC_GPDMA->INTTCCLEAR = irq_status; /* Clear DMA interrupt flag. */
|
||||
err_status = LPC_GPDMA->INTERRSTAT;
|
||||
LPC_GPDMA->INTERRCLR = err_status; /* Clear DMA error flag if any. */
|
||||
|
||||
for (i = 0; i < LPC_DMA_CHANNELS; i++) {
|
||||
if (irq_status & (1UL << i)) {
|
||||
if (dma_isr_redir[i].dma_func)
|
||||
dma_isr_redir[i].dma_func(dma_isr_redir[i].dma_param, err_status);
|
||||
}
|
||||
}
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC43xx DMA initialization.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void dmaInit(void) {
|
||||
uint8_t i;
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < LPC_DMA_CHANNELS; i++)
|
||||
_lpc_dma_channel_config[i]->config = 0;
|
||||
|
||||
LPC_GPDMA->INTTCCLEAR = 0xFF;
|
||||
LPC_GPDMA->INTERRCLR = 0xFF;
|
||||
|
||||
LPC_GPDMA->CONFIG = DMACCONFIG_E; /* Enable DMA Controller, little-endian mode */
|
||||
while((LPC_GPDMA->CONFIG & DMACCONFIG_E) != 0x01)
|
||||
;
|
||||
|
||||
nvicEnableVector(DMA_IRQn, CORTEX_PRIORITY_MASK(LPC_DMA_IRQ_PRIORITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a DMA channel.
|
||||
* @details The channel is allocated.
|
||||
* @pre The channel must not be already in use or an error is returned.
|
||||
* @post The channel is allocated and the default ISR handler redirected
|
||||
* to the specified function.
|
||||
* @post The channel must be freed using @p dmaChannelRelease() before it can
|
||||
* be reused with another peripheral.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] func handling function pointer, can be @p NULL
|
||||
* @param[in] param a parameter to be passed to the handling function
|
||||
* @return The operation status.
|
||||
* @retval FALSE no error, stream taken.
|
||||
* @retval TRUE error, stream already taken.
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
bool_t dmaChannelAllocate(lpc_dma_channel_t dmach,
|
||||
lpc_dmaisr_t func,
|
||||
void *param) {
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Checks if the channel is already taken.*/
|
||||
if ((dma_streams_mask & channel) != 0)
|
||||
return TRUE;
|
||||
|
||||
/* Marks the stream as allocated.*/
|
||||
dma_isr_redir[dmach].dma_func = func;
|
||||
dma_isr_redir[dmach].dma_param = param;
|
||||
dma_streams_mask |= channel;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a DMA channel.
|
||||
* @details The channel is freed.
|
||||
* Trying to release a unallocated channel is an illegal operation
|
||||
* and is trapped if assertions are enabled.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post The channel is again available.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
void dmaChannelRelease(lpc_dma_channel_t dmach) {
|
||||
|
||||
uint32_t channel;
|
||||
channel = (1UL << dmach);
|
||||
|
||||
/* Check if the streams is not taken.*/
|
||||
chDbgAssert((dma_streams_mask & channel) != 0,
|
||||
"dmaStreamRelease(), #1", "not allocated");
|
||||
|
||||
dma_streams_mask &= ~channel; /* Marks the stream as not allocated.*/
|
||||
}
|
||||
|
||||
#endif /* LPC_DMA_REQUIRED */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,472 +1,472 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/LPC43xx_dma.h
|
||||
* @brief DMA driver header.
|
||||
*
|
||||
* @addtogroup LPC43xx_DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LPC43xx_DMA_H_
|
||||
#define _LPC43xx_DMA_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define LPC_GPDMACH0 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x100))
|
||||
#define LPC_GPDMACH1 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x120))
|
||||
#define LPC_GPDMACH2 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x140))
|
||||
#define LPC_GPDMACH3 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x160))
|
||||
#define LPC_GPDMACH4 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x180))
|
||||
#define LPC_GPDMACH5 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1A0))
|
||||
#define LPC_GPDMACH6 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1C0))
|
||||
#define LPC_GPDMACH7 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1E0))
|
||||
|
||||
#define DMACCONFIG_E (1UL << 0)
|
||||
#define DMACCONFIG_M (1UL << 1)
|
||||
|
||||
/**
|
||||
* @brief Total number of DMA streams.
|
||||
* @note This is the total number of streams among all the DMA units.
|
||||
*/
|
||||
#define LPC_DMA_CHANNELS 8
|
||||
|
||||
/**
|
||||
* @name DMA control data configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA transfer size.
|
||||
*
|
||||
* @param[in] n DMA transfer size
|
||||
*/
|
||||
#define DMA_CTRL_TRANSFER_SIZE(n) (n)
|
||||
|
||||
/**
|
||||
* @brief DMA source burst size.
|
||||
*/
|
||||
#define DMA_CTRL_SRC_BSIZE_1 (0 << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_4 (1UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_8 (2UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_16 (3UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_32 (4UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_64 (5UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_128 (6UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_256 (7UL << 12)
|
||||
|
||||
/**
|
||||
* @brief DMA destination burst size.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_BSIZE_1 (0 << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_4 (1UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_8 (2UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_16 (3UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_32 (4UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_64 (5UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_128 (6UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_256 (7UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_WIDTH_BYTE (0 << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_HWORD (1UL << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_WORD (2UL << 18)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_WIDTH_BYTE (0 << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_HWORD (1UL << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_WORD (2UL << 21)
|
||||
|
||||
/**
|
||||
* @name DMA source, source AHB master select.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_AHBM0 (0 << 24)
|
||||
#define DMA_CTRL_SRC_AHBM1 (1 << 24)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination AHB master select.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_AHBM0 (0 << 25)
|
||||
#define DMA_CTRL_DST_AHBM1 (1 << 25)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_NOINC (0UL << 26)
|
||||
#define DMA_CTRL_SRC_INC (1UL << 26)
|
||||
|
||||
/**
|
||||
* @name DMA destination increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_NOINC (0UL << 27)
|
||||
#define DMA_CTRL_DST_INC (1UL << 27)
|
||||
|
||||
/**
|
||||
* @name DMA bus access bits.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_PROT1_USER (0 << 28)
|
||||
#define DMA_CTRL_PROT1_PRIV (1UL << 28)
|
||||
|
||||
#define DMA_CTRL_PROT2_NONBUFF (0 << 29)
|
||||
#define DMA_CTRL_PROT2_BUFF (1UL << 29)
|
||||
|
||||
#define DMA_CTRL_PROT3_NONCACHE (0 << 30)
|
||||
#define DMA_CTRL_PROT3_CACHE (1UL << 30)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA terminal count interrupt enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_INT (1UL << 31)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA channel enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_CH_ENABLE (1UL << 0)
|
||||
|
||||
/**
|
||||
* @brief Source peripheral.
|
||||
*
|
||||
* @param[in] source source peripheral
|
||||
*/
|
||||
#define DMA_CFG_SRC_PERIPH(src) ((src) << 1)
|
||||
|
||||
/**
|
||||
* @brief Destination peripheral.
|
||||
*
|
||||
* @param[in] destination destination peripheral
|
||||
*/
|
||||
#define DMA_CFG_DST_PERIPH(dst) ((dst) << 6)
|
||||
|
||||
/**
|
||||
* @name Flow control and transfer type.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_FCTRL_M2M (0UL << 11)
|
||||
#define DMA_CFG_FCTRL_M2P (1UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2M (2UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_DMA_CTRL (3UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_DST_CTRL (4UL << 11)
|
||||
#define DMA_CFG_FCTRL_M2P_PER_CTRL (5UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2M_PER_CTRL (6UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_SRC_CTRL (7UL << 11)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Interrupt error mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_IE (1UL << 14)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Terminal count interrupt mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ITC (1UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Active.
|
||||
* @note Read only
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ACTIVE (1UL << 17)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Halt.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_HALT (1UL << 18)
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name AHB master select for loading the next LLI.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_LLI_AHBM0 0
|
||||
#define DMA_LLI_AHBM1 1
|
||||
/** @} */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_DMA_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
volatile uint32_t config; /**< @brief Configuration. */
|
||||
} lpc_dma_channel_config_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
} lpc_dma_lli_config_t;
|
||||
|
||||
/**
|
||||
* @brief DMA channel number.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_CHANNEL0 = 0,
|
||||
DMA_CHANNEL1 = 1,
|
||||
DMA_CHANNEL2 = 2,
|
||||
DMA_CHANNEL3 = 3,
|
||||
DMA_CHANNEL4 = 4,
|
||||
DMA_CHANNEL5 = 5,
|
||||
DMA_CHANNEL6 = 6,
|
||||
DMA_CHANNEL7 = 7
|
||||
} lpc_dma_channel_t;
|
||||
|
||||
/**
|
||||
* @brief DMA source or destination type.
|
||||
*/
|
||||
typedef enum {
|
||||
PERIPHERAL0 = 0,
|
||||
PERIPHERAL1 = 1,
|
||||
PERIPHERAL2 = 2,
|
||||
PERIPHERAL3 = 3,
|
||||
PERIPHERAL4 = 4,
|
||||
PERIPHERAL5 = 5,
|
||||
PERIPHERAL6 = 6,
|
||||
PERIPHERAL7 = 7,
|
||||
PERIPHERAL8 = 8,
|
||||
PERIPHERAL9 = 9,
|
||||
PERIPHERAL10 = 10,
|
||||
PERIPHERAL11 = 11,
|
||||
PERIPHERAL12 = 12,
|
||||
PERIPHERAL13 = 13,
|
||||
PERIPHERAL14 = 14,
|
||||
PERIPHERAL15 = 15
|
||||
} lpc_dma_src_dst_t;
|
||||
|
||||
/**
|
||||
* @brief LPC DMA ISR function type.
|
||||
*
|
||||
* @param[in] p parameter for the registered function
|
||||
* @param[in] flags pre-shifted content of the xISR register, the bits
|
||||
* are aligned to bit zero
|
||||
*/
|
||||
typedef void (*lpc_dmaisr_t)(void *p, uint32_t flags);
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Macro Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set dma peripheral connection.
|
||||
*
|
||||
* @param[in] periphn dma peripheral connection number
|
||||
* @param[in] select selected peripheral
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaMuxSet(periphn, select) \
|
||||
LPC_CREG->DMAMUX &= ~(3UL << ((periphn) * 2)); \
|
||||
LPC_CREG->DMAMUX |= (select) << ((periphn) * 2)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory source to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a source address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelSrcAddr(dmach, addr) \
|
||||
_lpc_dma_channel_config[dmach]->srcaddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory destination to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a destination address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDstAddr(dmach, addr) \
|
||||
_lpc_dma_channel_config[dmach]->dstaddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a linked list item address to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a linked list item
|
||||
* @param[in] master AHB master select for loading next LLI, 0 or 1
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelLinkedList(dmach, addr, master) \
|
||||
_lpc_dma_channel_config[dmach]->lli = (((uint32_t)(addr)) | master)
|
||||
|
||||
/**
|
||||
* @brief Set control configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] ctrl control configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelControl(dmach, ctrl) \
|
||||
_lpc_dma_channel_config[dmach]->control = (ctrl)
|
||||
|
||||
/**
|
||||
* @brief Set configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAllocate().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] config dma channel configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelConfig(dmach, cfg) \
|
||||
_lpc_dma_channel_config[dmach]->config = (cfg)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software burst transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftBurstRequest(src) \
|
||||
LPC_GPDMA->SOFTBREQ = (1UL << (src))
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software single transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftSingleRequest(src) \
|
||||
LPC_GPDMA->SOFTSREQ = (1UL << (src))
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelEnable(dmach) \
|
||||
_lpc_dma_channel_config[dmach]->config |= (DMA_CFG_CH_ENABLE)
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDisable(dmach) \
|
||||
_lpc_dma_channel_config[dmach]->config &= ~(DMA_CFG_CH_ENABLE)
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern lpc_dma_channel_config_t * _lpc_dma_channel_config[];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dmaInit(void);
|
||||
bool_t dmaChannelAllocate(lpc_dma_channel_t dmach,
|
||||
lpc_dmaisr_t func,
|
||||
void *param);
|
||||
void dmaChannelRelease(lpc_dma_channel_t dmach);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LPC43xx_DMA_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
LPC43xx DMA driver - Copyright (C) 2013 Marcin Jokel
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/LPC43xx_dma.h
|
||||
* @brief DMA driver header.
|
||||
*
|
||||
* @addtogroup LPC43xx_DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LPC43xx_DMA_H_
|
||||
#define _LPC43xx_DMA_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define LPC_GPDMACH0 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x100))
|
||||
#define LPC_GPDMACH1 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x120))
|
||||
#define LPC_GPDMACH2 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x140))
|
||||
#define LPC_GPDMACH3 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x160))
|
||||
#define LPC_GPDMACH4 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x180))
|
||||
#define LPC_GPDMACH5 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1A0))
|
||||
#define LPC_GPDMACH6 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1C0))
|
||||
#define LPC_GPDMACH7 ((lpc_dma_channel_config_t *) (LPC_GPDMA_BASE + 0x1E0))
|
||||
|
||||
#define DMACCONFIG_E (1UL << 0)
|
||||
#define DMACCONFIG_M (1UL << 1)
|
||||
|
||||
/**
|
||||
* @brief Total number of DMA streams.
|
||||
* @note This is the total number of streams among all the DMA units.
|
||||
*/
|
||||
#define LPC_DMA_CHANNELS 8
|
||||
|
||||
/**
|
||||
* @name DMA control data configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA transfer size.
|
||||
*
|
||||
* @param[in] n DMA transfer size
|
||||
*/
|
||||
#define DMA_CTRL_TRANSFER_SIZE(n) (n)
|
||||
|
||||
/**
|
||||
* @brief DMA source burst size.
|
||||
*/
|
||||
#define DMA_CTRL_SRC_BSIZE_1 (0 << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_4 (1UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_8 (2UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_16 (3UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_32 (4UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_64 (5UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_128 (6UL << 12)
|
||||
#define DMA_CTRL_SRC_BSIZE_256 (7UL << 12)
|
||||
|
||||
/**
|
||||
* @brief DMA destination burst size.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_BSIZE_1 (0 << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_4 (1UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_8 (2UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_16 (3UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_32 (4UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_64 (5UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_128 (6UL << 15)
|
||||
#define DMA_CTRL_DST_BSIZE_256 (7UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_WIDTH_BYTE (0 << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_HWORD (1UL << 18)
|
||||
#define DMA_CTRL_SRC_WIDTH_WORD (2UL << 18)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination transfer width.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_WIDTH_BYTE (0 << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_HWORD (1UL << 21)
|
||||
#define DMA_CTRL_DST_WIDTH_WORD (2UL << 21)
|
||||
|
||||
/**
|
||||
* @name DMA source, source AHB master select.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_AHBM0 (0 << 24)
|
||||
#define DMA_CTRL_SRC_AHBM1 (1 << 24)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA destination AHB master select.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_AHBM0 (0 << 25)
|
||||
#define DMA_CTRL_DST_AHBM1 (1 << 25)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA source increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_SRC_NOINC (0UL << 26)
|
||||
#define DMA_CTRL_SRC_INC (1UL << 26)
|
||||
|
||||
/**
|
||||
* @name DMA destination increment after each transfer.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_DST_NOINC (0UL << 27)
|
||||
#define DMA_CTRL_DST_INC (1UL << 27)
|
||||
|
||||
/**
|
||||
* @name DMA bus access bits.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_PROT1_USER (0 << 28)
|
||||
#define DMA_CTRL_PROT1_PRIV (1UL << 28)
|
||||
|
||||
#define DMA_CTRL_PROT2_NONBUFF (0 << 29)
|
||||
#define DMA_CTRL_PROT2_BUFF (1UL << 29)
|
||||
|
||||
#define DMA_CTRL_PROT3_NONCACHE (0 << 30)
|
||||
#define DMA_CTRL_PROT3_CACHE (1UL << 30)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA terminal count interrupt enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CTRL_INT (1UL << 31)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA channel enable.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_CH_ENABLE (1UL << 0)
|
||||
|
||||
/**
|
||||
* @brief Source peripheral.
|
||||
*
|
||||
* @param[in] source source peripheral
|
||||
*/
|
||||
#define DMA_CFG_SRC_PERIPH(src) ((src) << 1)
|
||||
|
||||
/**
|
||||
* @brief Destination peripheral.
|
||||
*
|
||||
* @param[in] destination destination peripheral
|
||||
*/
|
||||
#define DMA_CFG_DST_PERIPH(dst) ((dst) << 6)
|
||||
|
||||
/**
|
||||
* @name Flow control and transfer type.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_FCTRL_M2M (0UL << 11)
|
||||
#define DMA_CFG_FCTRL_M2P (1UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2M (2UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_DMA_CTRL (3UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_DST_CTRL (4UL << 11)
|
||||
#define DMA_CFG_FCTRL_M2P_PER_CTRL (5UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2M_PER_CTRL (6UL << 11)
|
||||
#define DMA_CFG_FCTRL_P2P_SRC_CTRL (7UL << 11)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Interrupt error mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_IE (1UL << 14)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Terminal count interrupt mask.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ITC (1UL << 15)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Active.
|
||||
* @note Read only
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_ACTIVE (1UL << 17)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Halt.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_CFG_HALT (1UL << 18)
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name AHB master select for loading the next LLI.
|
||||
* @{
|
||||
*/
|
||||
#define DMA_LLI_AHBM0 0
|
||||
#define DMA_LLI_AHBM1 1
|
||||
/** @} */
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief DMA interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_DMA_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
volatile uint32_t config; /**< @brief Configuration. */
|
||||
} lpc_dma_channel_config_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t srcaddr; /**< @brief Source address. */
|
||||
volatile uint32_t dstaddr; /**< @brief Destination address. */
|
||||
volatile uint32_t lli; /**< @brief Linked List Item. */
|
||||
volatile uint32_t control; /**< @brief Control. */
|
||||
} lpc_dma_lli_config_t;
|
||||
|
||||
/**
|
||||
* @brief DMA channel number.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_CHANNEL0 = 0,
|
||||
DMA_CHANNEL1 = 1,
|
||||
DMA_CHANNEL2 = 2,
|
||||
DMA_CHANNEL3 = 3,
|
||||
DMA_CHANNEL4 = 4,
|
||||
DMA_CHANNEL5 = 5,
|
||||
DMA_CHANNEL6 = 6,
|
||||
DMA_CHANNEL7 = 7
|
||||
} lpc_dma_channel_t;
|
||||
|
||||
/**
|
||||
* @brief DMA source or destination type.
|
||||
*/
|
||||
typedef enum {
|
||||
PERIPHERAL0 = 0,
|
||||
PERIPHERAL1 = 1,
|
||||
PERIPHERAL2 = 2,
|
||||
PERIPHERAL3 = 3,
|
||||
PERIPHERAL4 = 4,
|
||||
PERIPHERAL5 = 5,
|
||||
PERIPHERAL6 = 6,
|
||||
PERIPHERAL7 = 7,
|
||||
PERIPHERAL8 = 8,
|
||||
PERIPHERAL9 = 9,
|
||||
PERIPHERAL10 = 10,
|
||||
PERIPHERAL11 = 11,
|
||||
PERIPHERAL12 = 12,
|
||||
PERIPHERAL13 = 13,
|
||||
PERIPHERAL14 = 14,
|
||||
PERIPHERAL15 = 15
|
||||
} lpc_dma_src_dst_t;
|
||||
|
||||
/**
|
||||
* @brief LPC DMA ISR function type.
|
||||
*
|
||||
* @param[in] p parameter for the registered function
|
||||
* @param[in] flags pre-shifted content of the xISR register, the bits
|
||||
* are aligned to bit zero
|
||||
*/
|
||||
typedef void (*lpc_dmaisr_t)(void *p, uint32_t flags);
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Macro Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set dma peripheral connection.
|
||||
*
|
||||
* @param[in] periphn dma peripheral connection number
|
||||
* @param[in] select selected peripheral
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaMuxSet(periphn, select) \
|
||||
LPC_CREG->DMAMUX &= ~(3UL << ((periphn) * 2)); \
|
||||
LPC_CREG->DMAMUX |= (select) << ((periphn) * 2)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory source to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a source address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelSrcAddr(dmach, addr) \
|
||||
_lpc_dma_channel_config[dmach]->srcaddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a memory destination to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a destination address
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDstAddr(dmach, addr) \
|
||||
_lpc_dma_channel_config[dmach]->dstaddr = (uint32_t)(addr)
|
||||
|
||||
/**
|
||||
* @brief Associates a linked list item address to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] addr pointer to a linked list item
|
||||
* @param[in] master AHB master select for loading next LLI, 0 or 1
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelLinkedList(dmach, addr, master) \
|
||||
_lpc_dma_channel_config[dmach]->lli = (((uint32_t)(addr)) | master)
|
||||
|
||||
/**
|
||||
* @brief Set control configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] ctrl control configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelControl(dmach, ctrl) \
|
||||
_lpc_dma_channel_config[dmach]->control = (ctrl)
|
||||
|
||||
/**
|
||||
* @brief Set configuration to a DMA channel.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaStreamAllocate().
|
||||
* @post After use the channel can be released using @p dmaStreamRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
* @param[in] config dma channel configuration value
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelConfig(dmach, cfg) \
|
||||
_lpc_dma_channel_config[dmach]->config = (cfg)
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software burst transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftBurstRequest(src) \
|
||||
LPC_GPDMA->SOFTBREQ = (1UL << (src))
|
||||
|
||||
/**
|
||||
* @brief Trigger DMA software single transfer request.
|
||||
*
|
||||
* @param[in] src peripheral source request
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaSoftSingleRequest(src) \
|
||||
LPC_GPDMA->SOFTSREQ = (1UL << (src))
|
||||
|
||||
/**
|
||||
* @brief DMA channel enable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelEnable(dmach) \
|
||||
_lpc_dma_channel_config[dmach]->config |= (DMA_CFG_CH_ENABLE)
|
||||
|
||||
/**
|
||||
* @brief DMA channel disable.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The channel must have been allocated using @p dmaChannelAllocate().
|
||||
* @post After use the channel can be released using @p dmaChannelRelease().
|
||||
*
|
||||
* @param[in] dmach DMA channel number
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaChannelDisable(dmach) \
|
||||
_lpc_dma_channel_config[dmach]->config &= ~(DMA_CFG_CH_ENABLE)
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern lpc_dma_channel_config_t * _lpc_dma_channel_config[];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void dmaInit(void);
|
||||
bool_t dmaChannelAllocate(lpc_dma_channel_t dmach,
|
||||
lpc_dmaisr_t func,
|
||||
void *param);
|
||||
void dmaChannelRelease(lpc_dma_channel_t dmach);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LPC43xx_DMA_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,171 +1,171 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file has been contributed by:
|
||||
Marcin Jokel.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/pal_lld.c
|
||||
* @brief LPC43xx GPIO low level driver code.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static void initgpio(ioportid_t port, const lpc_gpio_setup_t *config) {
|
||||
|
||||
LPC_GPIO_PORT->DIR[port] = config->dir;
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
LPC_GPIO_PORT->PIN[port] = config->data;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief LPC43xx I/O ports configuration.
|
||||
* @details GPIO unit registers initialization.
|
||||
*
|
||||
* @param[in] config the LPC43xx ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_init(const PALConfig *config) {
|
||||
|
||||
initgpio(GPIO0, &config->P0);
|
||||
initgpio(GPIO1, &config->P1);
|
||||
initgpio(GPIO2, &config->P2);
|
||||
initgpio(GPIO3, &config->P3);
|
||||
#if LPC_HAS_GPIO4
|
||||
initgpio(GPIO4, &config->P4);
|
||||
#endif
|
||||
initgpio(GPIO5, &config->P5);
|
||||
|
||||
#if LPC_HAS_GPIO6
|
||||
initgpio(GPIO6, &config->P6);
|
||||
#endif
|
||||
|
||||
#if LPC_HAS_GPIO7
|
||||
initgpio(GPIO7, &config->P7);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset) {
|
||||
|
||||
uint32_t p;
|
||||
|
||||
LPC_GPIO_PORT->MASK[port] = ~((mask) << offset);
|
||||
p = LPC_GPIO_PORT->MPIN[port];
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits) {
|
||||
|
||||
LPC_GPIO_PORT->MASK[port] = ~((mask) << offset);
|
||||
LPC_GPIO_PORT->MPIN[port] = bits;
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
}
|
||||
/**
|
||||
* @brief Pads mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with
|
||||
* high state.
|
||||
* @note This function does not alter the @p PINSELx registers. Alternate
|
||||
* functions setup must be handled by device-specific code.
|
||||
*
|
||||
* @param[in] port the port identifier
|
||||
* @param[in] mask the group mask
|
||||
* @param[in] mode the mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode) {
|
||||
|
||||
switch (mode) {
|
||||
case PAL_MODE_RESET:
|
||||
case PAL_MODE_INPUT:
|
||||
LPC_GPIO_PORT->DIR[port] &= ~mask;
|
||||
break;
|
||||
case PAL_MODE_UNCONNECTED:
|
||||
palSetPort(port, PAL_WHOLE_PORT);
|
||||
case PAL_MODE_OUTPUT_PUSHPULL:
|
||||
LPC_GPIO_PORT->DIR[port] |= mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file has been contributed by:
|
||||
Marcin Jokel.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/pal_lld.c
|
||||
* @brief LPC43xx GPIO low level driver code.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static void initgpio(ioportid_t port, const lpc_gpio_setup_t *config) {
|
||||
|
||||
LPC_GPIO_PORT->DIR[port] = config->dir;
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
LPC_GPIO_PORT->PIN[port] = config->data;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief LPC43xx I/O ports configuration.
|
||||
* @details GPIO unit registers initialization.
|
||||
*
|
||||
* @param[in] config the LPC43xx ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_init(const PALConfig *config) {
|
||||
|
||||
initgpio(GPIO0, &config->P0);
|
||||
initgpio(GPIO1, &config->P1);
|
||||
initgpio(GPIO2, &config->P2);
|
||||
initgpio(GPIO3, &config->P3);
|
||||
#if LPC_HAS_GPIO4
|
||||
initgpio(GPIO4, &config->P4);
|
||||
#endif
|
||||
initgpio(GPIO5, &config->P5);
|
||||
|
||||
#if LPC_HAS_GPIO6
|
||||
initgpio(GPIO6, &config->P6);
|
||||
#endif
|
||||
|
||||
#if LPC_HAS_GPIO7
|
||||
initgpio(GPIO7, &config->P7);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset) {
|
||||
|
||||
uint32_t p;
|
||||
|
||||
LPC_GPIO_PORT->MASK[port] = ~((mask) << offset);
|
||||
p = LPC_GPIO_PORT->MPIN[port];
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits) {
|
||||
|
||||
LPC_GPIO_PORT->MASK[port] = ~((mask) << offset);
|
||||
LPC_GPIO_PORT->MPIN[port] = bits;
|
||||
LPC_GPIO_PORT->MASK[port] = 0;
|
||||
}
|
||||
/**
|
||||
* @brief Pads mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with
|
||||
* high state.
|
||||
* @note This function does not alter the @p PINSELx registers. Alternate
|
||||
* functions setup must be handled by device-specific code.
|
||||
*
|
||||
* @param[in] port the port identifier
|
||||
* @param[in] mask the group mask
|
||||
* @param[in] mode the mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode) {
|
||||
|
||||
switch (mode) {
|
||||
case PAL_MODE_RESET:
|
||||
case PAL_MODE_INPUT:
|
||||
LPC_GPIO_PORT->DIR[port] &= ~mask;
|
||||
break;
|
||||
case PAL_MODE_UNCONNECTED:
|
||||
palSetPort(port, PAL_WHOLE_PORT);
|
||||
case PAL_MODE_OUTPUT_PUSHPULL:
|
||||
LPC_GPIO_PORT->DIR[port] |= mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,381 +1,381 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file has been contributed by:
|
||||
Marcin Jokel.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/pal_lld.h
|
||||
* @brief LPC43xx GPIO low level driver header.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _PAL_LLD_H_
|
||||
#define _PAL_LLD_H_
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Unsupported modes and specific modes */
|
||||
/*===========================================================================*/
|
||||
|
||||
#undef PAL_MODE_INPUT_PULLUP
|
||||
#undef PAL_MODE_INPUT_PULLDOWN
|
||||
#undef PAL_MODE_INPUT_ANALOG
|
||||
#undef PAL_MODE_OUTPUT_OPENDRAIN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Types and constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO port setup info.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Initial value for PIN register.*/
|
||||
uint32_t data;
|
||||
/** Initial value for DIR register.*/
|
||||
uint32_t dir;
|
||||
} lpc_gpio_setup_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO static initializer.
|
||||
* @details An instance of this structure must be passed to @p palInit() at
|
||||
* system startup time in order to initialized the digital I/O
|
||||
* subsystem. This represents only the initial setup, specific pads
|
||||
* or whole ports can be reprogrammed at later time.
|
||||
* @note The @p IOCON block is not configured, initially all pins have
|
||||
* enabled pullups and are programmed as GPIO. It is responsibility
|
||||
* of the various drivers to reprogram the pins in the proper mode.
|
||||
* Pins that are not handled by any driver may be programmed in
|
||||
* @p board.c.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief GPIO 0 setup data.*/
|
||||
lpc_gpio_setup_t P0;
|
||||
/** @brief GPIO 1 setup data.*/
|
||||
lpc_gpio_setup_t P1;
|
||||
/** @brief GPIO 2 setup data.*/
|
||||
lpc_gpio_setup_t P2;
|
||||
/** @brief GPIO 3 setup data.*/
|
||||
lpc_gpio_setup_t P3;
|
||||
#if LPC_HAS_GPIO4
|
||||
/** @brief GPIO 4 setup data.*/
|
||||
lpc_gpio_setup_t P4;
|
||||
#endif
|
||||
/** @brief GPIO 5 setup data.*/
|
||||
lpc_gpio_setup_t P5;
|
||||
#if LPC_HAS_GPIO6
|
||||
/** @brief GPIO 6 setup data.*/
|
||||
lpc_gpio_setup_t P6;
|
||||
#endif
|
||||
#if LPC_HAS_GPIO7
|
||||
/** @brief GPIO 7 setup data.*/
|
||||
lpc_gpio_setup_t P7;
|
||||
#endif
|
||||
} PALConfig;
|
||||
|
||||
/**
|
||||
* @brief Width, in bits, of an I/O port.
|
||||
*/
|
||||
#define PAL_IOPORTS_WIDTH 32
|
||||
|
||||
/**
|
||||
* @brief Whole port mask.
|
||||
* @brief This macro specifies all the valid bits into a port.
|
||||
*/
|
||||
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* @brief Digital I/O port sized unsigned type.
|
||||
*/
|
||||
typedef uint32_t ioportmask_t;
|
||||
|
||||
/**
|
||||
* @brief Digital I/O modes.
|
||||
*/
|
||||
typedef uint32_t iomode_t;
|
||||
|
||||
/**
|
||||
* @brief Port Identifier.
|
||||
*/
|
||||
typedef uint32_t ioportid_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Identifiers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO0 port identifier.
|
||||
*/
|
||||
#define IOPORT1 0
|
||||
#define GPIO0 0
|
||||
|
||||
/**
|
||||
* @brief GPIO1 port identifier.
|
||||
*/
|
||||
#define IOPORT2 1
|
||||
#define GPIO1 1
|
||||
|
||||
/**
|
||||
* @brief GPIO2 port identifier.
|
||||
*/
|
||||
#define IOPORT3 2
|
||||
#define GPIO2 2
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT4 3
|
||||
#define GPIO3 3
|
||||
|
||||
/**
|
||||
* @brief GPIO4 port identifier.
|
||||
*/
|
||||
#define IOPORT5 4
|
||||
#define GPIO4 4
|
||||
|
||||
/**
|
||||
* @brief GPIO5 port identifier.
|
||||
*/
|
||||
#define IOPORT6 5
|
||||
#define GPIO5 5
|
||||
|
||||
/**
|
||||
* @brief GPIO6 port identifier.
|
||||
*/
|
||||
#define IOPORT7 6
|
||||
#define GPIO6 6
|
||||
|
||||
/**
|
||||
* @brief GPIO7 port identifier.
|
||||
*/
|
||||
#define IOPORT8 7
|
||||
#define GPIO7 7
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Implementation, some of the following macros could be implemented as */
|
||||
/* functions, if so please put them in pal_lld.c. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level PAL subsystem initialization.
|
||||
*
|
||||
* @param[in] config architecture-dependent ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_init(config) _pal_lld_init(config)
|
||||
|
||||
/**
|
||||
* @brief Reads the physical I/O port states.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The port bits.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readport(port) (LPC_GPIO_PORT->PIN[port])
|
||||
|
||||
/**
|
||||
* @brief Reads the output latch.
|
||||
* @details The purpose of this function is to read back the latched output
|
||||
* value.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The latched logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readlatch(port) (LPC_GPIO_PORT->PIN[port])
|
||||
|
||||
/**
|
||||
* @brief Writes a bits mask on a I/O port.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be written on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writeport(port, bits) (LPC_GPIO_PORT->PIN[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Sets a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be ORed on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setport(port, bits) (LPC_GPIO_PORT->SET[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Clears a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be cleared on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearport(port, bits) (LPC_GPIO_PORT->CLR[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readgroup(port, mask, offset) \
|
||||
_pal_lld_readgroup(port, mask, offset)
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writegroup(port, mask, offset, bits) \
|
||||
_pal_lld_writegroup(port, mask, offset, bits)
|
||||
|
||||
/**
|
||||
* @brief Pads group mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note Programming an unknown or unsupported mode is silently ignored.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] mode group mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setgroupmode(port, mask, offset, mode) \
|
||||
_pal_lld_setgroupmode(port, mask << offset, mode)
|
||||
|
||||
/**
|
||||
* @brief Writes a logical state on an output pad.
|
||||
* @note This function is not meant to be invoked directly by the
|
||||
* application code.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
* @param[in] bit logical value, the value must be @p PAL_LOW or
|
||||
* @p PAL_HIGH
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writepad(port, pad, bit) \
|
||||
((bit) == PAL_LOW) ? pal_lld_clearpad(port, pad) : \
|
||||
pal_lld_setpad(port, pad)
|
||||
|
||||
/**
|
||||
* @brief Sets a pad logical state to @p PAL_HIGH.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setpad(port, pad) \
|
||||
(LPC_GPIO_PORT->SET[port] = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Clears a pad logical state to @p PAL_LOW.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearpad(port, pad) \
|
||||
(LPC_GPIO_PORT->CLR[port] = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Toggles a pad logical state.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_togglepad(port, pad) \
|
||||
(LPC_GPIO_PORT->NOT[port] = 1UL << (pad))
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern const PALConfig pal_default_config;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void _pal_lld_init(const PALConfig *config);
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset);
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits);
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
#endif /* _PAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
This file has been contributed by:
|
||||
Marcin Jokel.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/pal_lld.h
|
||||
* @brief LPC43xx GPIO low level driver header.
|
||||
*
|
||||
* @addtogroup PAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _PAL_LLD_H_
|
||||
#define _PAL_LLD_H_
|
||||
|
||||
#if HAL_USE_PAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Unsupported modes and specific modes */
|
||||
/*===========================================================================*/
|
||||
|
||||
#undef PAL_MODE_INPUT_PULLUP
|
||||
#undef PAL_MODE_INPUT_PULLDOWN
|
||||
#undef PAL_MODE_INPUT_ANALOG
|
||||
#undef PAL_MODE_OUTPUT_OPENDRAIN
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Types and constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO port setup info.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Initial value for PIN register.*/
|
||||
uint32_t data;
|
||||
/** Initial value for DIR register.*/
|
||||
uint32_t dir;
|
||||
} lpc_gpio_setup_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO static initializer.
|
||||
* @details An instance of this structure must be passed to @p palInit() at
|
||||
* system startup time in order to initialized the digital I/O
|
||||
* subsystem. This represents only the initial setup, specific pads
|
||||
* or whole ports can be reprogrammed at later time.
|
||||
* @note The @p IOCON block is not configured, initially all pins have
|
||||
* enabled pullups and are programmed as GPIO. It is responsibility
|
||||
* of the various drivers to reprogram the pins in the proper mode.
|
||||
* Pins that are not handled by any driver may be programmed in
|
||||
* @p board.c.
|
||||
*/
|
||||
typedef struct {
|
||||
/** @brief GPIO 0 setup data.*/
|
||||
lpc_gpio_setup_t P0;
|
||||
/** @brief GPIO 1 setup data.*/
|
||||
lpc_gpio_setup_t P1;
|
||||
/** @brief GPIO 2 setup data.*/
|
||||
lpc_gpio_setup_t P2;
|
||||
/** @brief GPIO 3 setup data.*/
|
||||
lpc_gpio_setup_t P3;
|
||||
#if LPC_HAS_GPIO4
|
||||
/** @brief GPIO 4 setup data.*/
|
||||
lpc_gpio_setup_t P4;
|
||||
#endif
|
||||
/** @brief GPIO 5 setup data.*/
|
||||
lpc_gpio_setup_t P5;
|
||||
#if LPC_HAS_GPIO6
|
||||
/** @brief GPIO 6 setup data.*/
|
||||
lpc_gpio_setup_t P6;
|
||||
#endif
|
||||
#if LPC_HAS_GPIO7
|
||||
/** @brief GPIO 7 setup data.*/
|
||||
lpc_gpio_setup_t P7;
|
||||
#endif
|
||||
} PALConfig;
|
||||
|
||||
/**
|
||||
* @brief Width, in bits, of an I/O port.
|
||||
*/
|
||||
#define PAL_IOPORTS_WIDTH 32
|
||||
|
||||
/**
|
||||
* @brief Whole port mask.
|
||||
* @brief This macro specifies all the valid bits into a port.
|
||||
*/
|
||||
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* @brief Digital I/O port sized unsigned type.
|
||||
*/
|
||||
typedef uint32_t ioportmask_t;
|
||||
|
||||
/**
|
||||
* @brief Digital I/O modes.
|
||||
*/
|
||||
typedef uint32_t iomode_t;
|
||||
|
||||
/**
|
||||
* @brief Port Identifier.
|
||||
*/
|
||||
typedef uint32_t ioportid_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I/O Ports Identifiers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief GPIO0 port identifier.
|
||||
*/
|
||||
#define IOPORT1 0
|
||||
#define GPIO0 0
|
||||
|
||||
/**
|
||||
* @brief GPIO1 port identifier.
|
||||
*/
|
||||
#define IOPORT2 1
|
||||
#define GPIO1 1
|
||||
|
||||
/**
|
||||
* @brief GPIO2 port identifier.
|
||||
*/
|
||||
#define IOPORT3 2
|
||||
#define GPIO2 2
|
||||
|
||||
/**
|
||||
* @brief GPIO3 port identifier.
|
||||
*/
|
||||
#define IOPORT4 3
|
||||
#define GPIO3 3
|
||||
|
||||
/**
|
||||
* @brief GPIO4 port identifier.
|
||||
*/
|
||||
#define IOPORT5 4
|
||||
#define GPIO4 4
|
||||
|
||||
/**
|
||||
* @brief GPIO5 port identifier.
|
||||
*/
|
||||
#define IOPORT6 5
|
||||
#define GPIO5 5
|
||||
|
||||
/**
|
||||
* @brief GPIO6 port identifier.
|
||||
*/
|
||||
#define IOPORT7 6
|
||||
#define GPIO6 6
|
||||
|
||||
/**
|
||||
* @brief GPIO7 port identifier.
|
||||
*/
|
||||
#define IOPORT8 7
|
||||
#define GPIO7 7
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Implementation, some of the following macros could be implemented as */
|
||||
/* functions, if so please put them in pal_lld.c. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level PAL subsystem initialization.
|
||||
*
|
||||
* @param[in] config architecture-dependent ports configuration
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_init(config) _pal_lld_init(config)
|
||||
|
||||
/**
|
||||
* @brief Reads the physical I/O port states.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The port bits.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readport(port) (LPC_GPIO_PORT->PIN[port])
|
||||
|
||||
/**
|
||||
* @brief Reads the output latch.
|
||||
* @details The purpose of this function is to read back the latched output
|
||||
* value.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @return The latched logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readlatch(port) (LPC_GPIO_PORT->PIN[port])
|
||||
|
||||
/**
|
||||
* @brief Writes a bits mask on a I/O port.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be written on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writeport(port, bits) (LPC_GPIO_PORT->PIN[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Sets a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be ORed on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setport(port, bits) (LPC_GPIO_PORT->SET[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Clears a bits mask on a I/O port.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] bits bits to be cleared on the specified port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearport(port, bits) (LPC_GPIO_PORT->CLR[port] = (bits))
|
||||
|
||||
/**
|
||||
* @brief Reads a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @return The group logical states.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_readgroup(port, mask, offset) \
|
||||
_pal_lld_readgroup(port, mask, offset)
|
||||
|
||||
/**
|
||||
* @brief Writes a group of bits.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] bits bits to be written. Values exceeding the group width
|
||||
* are masked.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writegroup(port, mask, offset, bits) \
|
||||
_pal_lld_writegroup(port, mask, offset, bits)
|
||||
|
||||
/**
|
||||
* @brief Pads group mode setup.
|
||||
* @details This function programs a pads group belonging to the same port
|
||||
* with the specified mode.
|
||||
* @note Programming an unknown or unsupported mode is silently ignored.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] mask group mask
|
||||
* @param[in] offset group bit offset within the port
|
||||
* @param[in] mode group mode
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setgroupmode(port, mask, offset, mode) \
|
||||
_pal_lld_setgroupmode(port, mask << offset, mode)
|
||||
|
||||
/**
|
||||
* @brief Writes a logical state on an output pad.
|
||||
* @note This function is not meant to be invoked directly by the
|
||||
* application code.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
* @param[in] bit logical value, the value must be @p PAL_LOW or
|
||||
* @p PAL_HIGH
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_writepad(port, pad, bit) \
|
||||
((bit) == PAL_LOW) ? pal_lld_clearpad(port, pad) : \
|
||||
pal_lld_setpad(port, pad)
|
||||
|
||||
/**
|
||||
* @brief Sets a pad logical state to @p PAL_HIGH.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_setpad(port, pad) \
|
||||
(LPC_GPIO_PORT->SET[port] = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Clears a pad logical state to @p PAL_LOW.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_clearpad(port, pad) \
|
||||
(LPC_GPIO_PORT->CLR[port] = 1UL << (pad))
|
||||
|
||||
/**
|
||||
* @brief Toggles a pad logical state.
|
||||
* @note The @ref PAL provides a default software implementation of this
|
||||
* functionality, implement this function if can optimize it by using
|
||||
* special hardware functionalities or special coding.
|
||||
*
|
||||
* @param[in] port port identifier
|
||||
* @param[in] pad pad number within the port
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define pal_lld_togglepad(port, pad) \
|
||||
(LPC_GPIO_PORT->NOT[port] = 1UL << (pad))
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern const PALConfig pal_default_config;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void _pal_lld_init(const PALConfig *config);
|
||||
uint32_t _pal_lld_readgroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset);
|
||||
void _pal_lld_writegroup(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
uint32_t offset,
|
||||
uint32_t bits);
|
||||
void _pal_lld_setgroupmode(ioportid_t port,
|
||||
ioportmask_t mask,
|
||||
iomode_t mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_PAL */
|
||||
|
||||
#endif /* _PAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# List of all the LPC43xx platform files.
|
||||
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC43xx/hal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/pal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/serial_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/gpt_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/spi_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/lpc43xx_dma.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/mac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/dac_lld.c
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC43xx
|
||||
# List of all the LPC43xx platform files.
|
||||
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/LPC43xx/hal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/pal_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/serial_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/gpt_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/spi_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/lpc43xx_dma.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/mac_lld.c \
|
||||
${CHIBIOS}/os/hal/platforms/LPC43xx/dac_lld.c
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/LPC43xx
|
||||
|
|
|
@ -1,476 +1,476 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/serial_lld.c
|
||||
* @brief LPC43xx low level serial driver code.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
/** @brief UART0 serial driver identifier.*/
|
||||
SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
/** @brief UART1 serial driver identifier.*/
|
||||
SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
/** @brief UART2 serial driver identifier.*/
|
||||
SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
/** @brief UART3 serial driver identifier.*/
|
||||
SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief Driver default configuration.*/
|
||||
static const SerialConfig default_config = {
|
||||
SERIAL_DEFAULT_BITRATE,
|
||||
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
|
||||
FCR_TRIGGER0
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART initialization.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] config the architecture-dependent serial driver configuration
|
||||
*/
|
||||
static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
uint32_t div = 0;
|
||||
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
div = LPC_SERIAL_UART0_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
div = LPC_SERIAL_UART1_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
div = LPC_SERIAL_UART2_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
div = LPC_SERIAL_UART3_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
u->LCR = config->sc_lcr | LCR_DLAB;
|
||||
u->DLL = div;
|
||||
u->DLM = div >> 8;
|
||||
u->LCR = config->sc_lcr;
|
||||
u->FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_fcr;
|
||||
u->ACR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->TER = TER_ENABLE;
|
||||
u->IER = IER_RBR | IER_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART de-initialization.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
*/
|
||||
static void uart_deinit(LPC_USARTn_Type *u) {
|
||||
|
||||
u->LCR = LCR_DLAB;
|
||||
u->DLL = 1;
|
||||
u->DLM = 0;
|
||||
u->LCR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->IER = 0;
|
||||
u->FCR = FCR_RXRESET | FCR_TXRESET;
|
||||
u->ACR = 0;
|
||||
u->TER = TER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error handling routine.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] err UART LSR register value
|
||||
*/
|
||||
static void set_error(SerialDriver *sdp, IOREG32 err) {
|
||||
flagsmask_t sts = 0;
|
||||
|
||||
if (err & LSR_OVERRUN)
|
||||
sts |= SD_OVERRUN_ERROR;
|
||||
if (err & LSR_PARITY)
|
||||
sts |= SD_PARITY_ERROR;
|
||||
if (err & LSR_FRAMING)
|
||||
sts |= SD_FRAMING_ERROR;
|
||||
if (err & LSR_BREAK)
|
||||
sts |= SD_BREAK_DETECTED;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, sts);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
* @note Tries hard to clear all the pending interrupt sources, we don't
|
||||
* want to go through the whole ISR and have another interrupt soon
|
||||
* after.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
*/
|
||||
static void serve_interrupt(SerialDriver *sdp) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
|
||||
while (TRUE) {
|
||||
switch (u->IIR & IIR_SRC_MASK) {
|
||||
case IIR_SRC_NONE:
|
||||
return;
|
||||
case IIR_SRC_ERROR:
|
||||
set_error(sdp, u->LSR);
|
||||
break;
|
||||
case IIR_SRC_TIMEOUT:
|
||||
case IIR_SRC_RX:
|
||||
chSysLockFromIsr();
|
||||
if (chIQIsEmptyI(&sdp->iqueue))
|
||||
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
|
||||
chSysUnlockFromIsr();
|
||||
while (u->LSR & LSR_RBR_FULL) {
|
||||
chSysLockFromIsr();
|
||||
if (chIQPutI(&sdp->iqueue, u->RBR) < Q_OK)
|
||||
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
break;
|
||||
case IIR_SRC_TX:
|
||||
{
|
||||
int i = LPC_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b;
|
||||
|
||||
chSysLockFromIsr();
|
||||
b = chOQGetI(&sdp->oqueue);
|
||||
chSysUnlockFromIsr();
|
||||
if (b < Q_OK) {
|
||||
u->IER &= ~IER_THRE;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
chSysUnlockFromIsr();
|
||||
break;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
(void) u->THR;
|
||||
(void) u->RBR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts a TX FIFO preload.
|
||||
*/
|
||||
static void preload(SerialDriver *sdp) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
|
||||
if (u->LSR & LSR_THRE) {
|
||||
int i = LPC_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b = chOQGetI(&sdp->oqueue);
|
||||
if (b < Q_OK) {
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
return;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
u->IER |= IER_THRE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Driver SD1 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
static void notify1(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD2 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
static void notify2(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD3 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
static void notify3(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD3);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD4 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
static void notify4(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD4);
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA0) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA4) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA8) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorAC) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_init(void) {
|
||||
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
sdObjectInit(&SD1, NULL, notify1);
|
||||
SD1.uart = ( LPC_USARTn_Type*) LPC_USART0;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
sdObjectInit(&SD2, NULL, notify2);
|
||||
SD2.uart = ( LPC_USARTn_Type*) LPC_UART1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
sdObjectInit(&SD3, NULL, notify3);
|
||||
SD3.uart = ( LPC_USARTn_Type*) LPC_USART2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
sdObjectInit(&SD4, NULL, notify4);
|
||||
SD4.uart = ( LPC_USARTn_Type*) LPC_USART3;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver configuration and (re)start.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
* @param[in] config the architecture-dependent serial driver configuration.
|
||||
* If this parameter is set to @p NULL then a default
|
||||
* configuration is used.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
|
||||
if (config == NULL)
|
||||
config = &default_config;
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG = 1;
|
||||
nvicEnableVector(USART0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG = 1;
|
||||
nvicEnableVector(UART1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG = 1;
|
||||
nvicEnableVector(USART2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG = 1;
|
||||
nvicEnableVector(USART3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
uart_init(sdp, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver stop.
|
||||
* @details De-initializes the UART, stops the associated clock, resets the
|
||||
* interrupt vector.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_stop(SerialDriver *sdp) {
|
||||
|
||||
if (sdp->state == SD_READY) {
|
||||
uart_deinit(sdp->uart);
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG = 0;
|
||||
nvicDisableVector(USART0_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG = 0;
|
||||
nvicDisableVector(UART1_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG = 0;
|
||||
nvicDisableVector(USART2_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG = 0;
|
||||
nvicDisableVector(USART3_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/serial_lld.c
|
||||
* @brief LPC43xx low level serial driver code.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
/** @brief UART0 serial driver identifier.*/
|
||||
SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
/** @brief UART1 serial driver identifier.*/
|
||||
SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
/** @brief UART2 serial driver identifier.*/
|
||||
SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
/** @brief UART3 serial driver identifier.*/
|
||||
SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief Driver default configuration.*/
|
||||
static const SerialConfig default_config = {
|
||||
SERIAL_DEFAULT_BITRATE,
|
||||
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
|
||||
FCR_TRIGGER0
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART initialization.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] config the architecture-dependent serial driver configuration
|
||||
*/
|
||||
static void uart_init(SerialDriver *sdp, const SerialConfig *config) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
uint32_t div = 0;
|
||||
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
div = LPC_SERIAL_UART0_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
div = LPC_SERIAL_UART1_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
div = LPC_SERIAL_UART2_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
div = LPC_SERIAL_UART3_PCLK / (config->sc_speed << 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
u->LCR = config->sc_lcr | LCR_DLAB;
|
||||
u->DLL = div;
|
||||
u->DLM = div >> 8;
|
||||
u->LCR = config->sc_lcr;
|
||||
u->FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->sc_fcr;
|
||||
u->ACR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->TER = TER_ENABLE;
|
||||
u->IER = IER_RBR | IER_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART de-initialization.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
*/
|
||||
static void uart_deinit(LPC_USARTn_Type *u) {
|
||||
|
||||
u->LCR = LCR_DLAB;
|
||||
u->DLL = 1;
|
||||
u->DLM = 0;
|
||||
u->LCR = 0;
|
||||
u->FDR = 0x10;
|
||||
u->IER = 0;
|
||||
u->FCR = FCR_RXRESET | FCR_TXRESET;
|
||||
u->ACR = 0;
|
||||
u->TER = TER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error handling routine.
|
||||
*
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
* @param[in] err UART LSR register value
|
||||
*/
|
||||
static void set_error(SerialDriver *sdp, IOREG32 err) {
|
||||
flagsmask_t sts = 0;
|
||||
|
||||
if (err & LSR_OVERRUN)
|
||||
sts |= SD_OVERRUN_ERROR;
|
||||
if (err & LSR_PARITY)
|
||||
sts |= SD_PARITY_ERROR;
|
||||
if (err & LSR_FRAMING)
|
||||
sts |= SD_FRAMING_ERROR;
|
||||
if (err & LSR_BREAK)
|
||||
sts |= SD_BREAK_DETECTED;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, sts);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
* @note Tries hard to clear all the pending interrupt sources, we don't
|
||||
* want to go through the whole ISR and have another interrupt soon
|
||||
* after.
|
||||
*
|
||||
* @param[in] u pointer to an UART I/O block
|
||||
* @param[in] sdp communication channel associated to the UART
|
||||
*/
|
||||
static void serve_interrupt(SerialDriver *sdp) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
|
||||
while (TRUE) {
|
||||
switch (u->IIR & IIR_SRC_MASK) {
|
||||
case IIR_SRC_NONE:
|
||||
return;
|
||||
case IIR_SRC_ERROR:
|
||||
set_error(sdp, u->LSR);
|
||||
break;
|
||||
case IIR_SRC_TIMEOUT:
|
||||
case IIR_SRC_RX:
|
||||
chSysLockFromIsr();
|
||||
if (chIQIsEmptyI(&sdp->iqueue))
|
||||
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
|
||||
chSysUnlockFromIsr();
|
||||
while (u->LSR & LSR_RBR_FULL) {
|
||||
chSysLockFromIsr();
|
||||
if (chIQPutI(&sdp->iqueue, u->RBR) < Q_OK)
|
||||
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
|
||||
chSysUnlockFromIsr();
|
||||
}
|
||||
break;
|
||||
case IIR_SRC_TX:
|
||||
{
|
||||
int i = LPC_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b;
|
||||
|
||||
chSysLockFromIsr();
|
||||
b = chOQGetI(&sdp->oqueue);
|
||||
chSysUnlockFromIsr();
|
||||
if (b < Q_OK) {
|
||||
u->IER &= ~IER_THRE;
|
||||
chSysLockFromIsr();
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
chSysUnlockFromIsr();
|
||||
break;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
(void) u->THR;
|
||||
(void) u->RBR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts a TX FIFO preload.
|
||||
*/
|
||||
static void preload(SerialDriver *sdp) {
|
||||
LPC_USARTn_Type *u = sdp->uart;
|
||||
|
||||
if (u->LSR & LSR_THRE) {
|
||||
int i = LPC_SERIAL_FIFO_PRELOAD;
|
||||
do {
|
||||
msg_t b = chOQGetI(&sdp->oqueue);
|
||||
if (b < Q_OK) {
|
||||
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
|
||||
return;
|
||||
}
|
||||
u->THR = b;
|
||||
} while (--i);
|
||||
}
|
||||
u->IER |= IER_THRE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Driver SD1 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
static void notify1(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD2 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
static void notify2(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD3 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
static void notify3(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD3);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Driver SD4 output notification.
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
static void notify4(GenericQueue *qp) {
|
||||
|
||||
(void)qp;
|
||||
preload(&SD4);
|
||||
}
|
||||
#endif
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART0 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA0) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART1 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA4) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART2 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorA8) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD3);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 IRQ handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
#if LPC_SERIAL_USE_UART3 || defined(__DOXYGEN__)
|
||||
CH_IRQ_HANDLER(VectorAC) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
serve_interrupt(&SD4);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_init(void) {
|
||||
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
sdObjectInit(&SD1, NULL, notify1);
|
||||
SD1.uart = ( LPC_USARTn_Type*) LPC_USART0;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
sdObjectInit(&SD2, NULL, notify2);
|
||||
SD2.uart = ( LPC_USARTn_Type*) LPC_UART1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
sdObjectInit(&SD3, NULL, notify3);
|
||||
SD3.uart = ( LPC_USARTn_Type*) LPC_USART2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
sdObjectInit(&SD4, NULL, notify4);
|
||||
SD4.uart = ( LPC_USARTn_Type*) LPC_USART3;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver configuration and (re)start.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
* @param[in] config the architecture-dependent serial driver configuration.
|
||||
* If this parameter is set to @p NULL then a default
|
||||
* configuration is used.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
|
||||
if (config == NULL)
|
||||
config = &default_config;
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG = 1;
|
||||
nvicEnableVector(USART0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG = 1;
|
||||
nvicEnableVector(UART1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG = 1;
|
||||
nvicEnableVector(USART2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG = 1;
|
||||
nvicEnableVector(USART3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
uart_init(sdp, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Low level serial driver stop.
|
||||
* @details De-initializes the UART, stops the associated clock, resets the
|
||||
* interrupt vector.
|
||||
*
|
||||
* @param[in] sdp pointer to a @p SerialDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void sd_lld_stop(SerialDriver *sdp) {
|
||||
|
||||
if (sdp->state == SD_READY) {
|
||||
uart_deinit(sdp->uart);
|
||||
#if LPC_SERIAL_USE_UART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG = 0;
|
||||
nvicDisableVector(USART0_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG = 0;
|
||||
nvicDisableVector(UART1_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG = 0;
|
||||
nvicDisableVector(USART2_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG = 0;
|
||||
nvicDisableVector(USART3_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,268 +1,268 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/serial_lld.h
|
||||
* @brief LPC43xx low level serial driver header.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_LLD_H_
|
||||
#define _SERIAL_LLD_H_
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define IIR_SRC_MASK 0x0F
|
||||
#define IIR_SRC_NONE 0x01
|
||||
#define IIR_SRC_MODEM 0x00
|
||||
#define IIR_SRC_TX 0x02
|
||||
#define IIR_SRC_RX 0x04
|
||||
#define IIR_SRC_ERROR 0x06
|
||||
#define IIR_SRC_TIMEOUT 0x0C
|
||||
|
||||
#define IER_RBR 1
|
||||
#define IER_THRE 2
|
||||
#define IER_STATUS 4
|
||||
|
||||
#define LCR_WL5 0
|
||||
#define LCR_WL6 1
|
||||
#define LCR_WL7 2
|
||||
#define LCR_WL8 3
|
||||
#define LCR_STOP1 0
|
||||
#define LCR_STOP2 4
|
||||
#define LCR_NOPARITY 0
|
||||
#define LCR_PARITYODD 0x08
|
||||
#define LCR_PARITYEVEN 0x18
|
||||
#define LCR_PARITYONE 0x28
|
||||
#define LCR_PARITYZERO 0x38
|
||||
#define LCR_BREAK_ON 0x40
|
||||
#define LCR_DLAB 0x80
|
||||
|
||||
#define FCR_ENABLE 1
|
||||
#define FCR_RXRESET 2
|
||||
#define FCR_TXRESET 4
|
||||
#define FCR_TRIGGER0 0
|
||||
#define FCR_TRIGGER1 0x40
|
||||
#define FCR_TRIGGER2 0x80
|
||||
#define FCR_TRIGGER3 0xC0
|
||||
|
||||
#define LSR_RBR_FULL 1
|
||||
#define LSR_OVERRUN 2
|
||||
#define LSR_PARITY 4
|
||||
#define LSR_FRAMING 8
|
||||
#define LSR_BREAK 0x10
|
||||
#define LSR_THRE 0x20
|
||||
#define LSR_TEMT 0x40
|
||||
#define LSR_RXFE 0x80
|
||||
|
||||
#define TER_ENABLE 0x01
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART0 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART0) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART1 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART1) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART2 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART2) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART3 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART3) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief FIFO preload parameter.
|
||||
* @details Configuration parameter, this values defines how many bytes are
|
||||
* preloaded in the HW transmit FIFO for each interrupt, the maximum
|
||||
* value is 16 the minimum is 1.
|
||||
* @note An high value reduces the number of interrupts generated but can
|
||||
* also increase the worst case interrupt response time because the
|
||||
* preload loops.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_FIFO_PRELOAD) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_FIFO_PRELOAD 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART3_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
#if (LPC_SERIAL_FIFO_PRELOAD < 1) || (LPC_SERIAL_FIFO_PRELOAD > 16)
|
||||
#error "invalid LPC_SERIAL_FIFO_PRELOAD setting"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART0_PCLK LPC_BASE_UART0_CLK
|
||||
|
||||
/**
|
||||
* @brief UART1 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART1_PCLK LPC_BASE_UART1_CLK
|
||||
|
||||
/**
|
||||
* @brief UART2 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART2_PCLK LPC_BASE_UART2_CLK
|
||||
|
||||
/**
|
||||
* @brief UART3 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART3_PCLK LPC_BASE_UART3_CLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx Serial Driver configuration structure.
|
||||
* @details An instance of this structure must be passed to @p sdStart()
|
||||
* in order to configure and start a serial driver operations.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Bit rate.
|
||||
*/
|
||||
uint32_t sc_speed;
|
||||
/**
|
||||
* @brief Initialization value for the LCR register.
|
||||
*/
|
||||
uint32_t sc_lcr;
|
||||
/**
|
||||
* @brief Initialization value for the FCR register.
|
||||
*/
|
||||
uint32_t sc_fcr;
|
||||
} SerialConfig;
|
||||
|
||||
/**
|
||||
* @brief @p SerialDriver specific data.
|
||||
*/
|
||||
#define _serial_driver_data \
|
||||
_base_asynchronous_channel_data \
|
||||
/* Driver state.*/ \
|
||||
sdstate_t state; \
|
||||
/* Input queue.*/ \
|
||||
InputQueue iqueue; \
|
||||
/* Output queue.*/ \
|
||||
OutputQueue oqueue; \
|
||||
/* Input circular buffer.*/ \
|
||||
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
|
||||
/* Output circular buffer.*/ \
|
||||
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
|
||||
/* End of the mandatory fields.*/ \
|
||||
/* Pointer to the USART registers block.*/ \
|
||||
LPC_USARTn_Type *uart;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void sd_lld_init(void);
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
|
||||
void sd_lld_stop(SerialDriver *sdp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
#endif /* _SERIAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/serial_lld.h
|
||||
* @brief LPC43xx low level serial driver header.
|
||||
*
|
||||
* @addtogroup SERIAL
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_LLD_H_
|
||||
#define _SERIAL_LLD_H_
|
||||
|
||||
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define IIR_SRC_MASK 0x0F
|
||||
#define IIR_SRC_NONE 0x01
|
||||
#define IIR_SRC_MODEM 0x00
|
||||
#define IIR_SRC_TX 0x02
|
||||
#define IIR_SRC_RX 0x04
|
||||
#define IIR_SRC_ERROR 0x06
|
||||
#define IIR_SRC_TIMEOUT 0x0C
|
||||
|
||||
#define IER_RBR 1
|
||||
#define IER_THRE 2
|
||||
#define IER_STATUS 4
|
||||
|
||||
#define LCR_WL5 0
|
||||
#define LCR_WL6 1
|
||||
#define LCR_WL7 2
|
||||
#define LCR_WL8 3
|
||||
#define LCR_STOP1 0
|
||||
#define LCR_STOP2 4
|
||||
#define LCR_NOPARITY 0
|
||||
#define LCR_PARITYODD 0x08
|
||||
#define LCR_PARITYEVEN 0x18
|
||||
#define LCR_PARITYONE 0x28
|
||||
#define LCR_PARITYZERO 0x38
|
||||
#define LCR_BREAK_ON 0x40
|
||||
#define LCR_DLAB 0x80
|
||||
|
||||
#define FCR_ENABLE 1
|
||||
#define FCR_RXRESET 2
|
||||
#define FCR_TXRESET 4
|
||||
#define FCR_TRIGGER0 0
|
||||
#define FCR_TRIGGER1 0x40
|
||||
#define FCR_TRIGGER2 0x80
|
||||
#define FCR_TRIGGER3 0xC0
|
||||
|
||||
#define LSR_RBR_FULL 1
|
||||
#define LSR_OVERRUN 2
|
||||
#define LSR_PARITY 4
|
||||
#define LSR_FRAMING 8
|
||||
#define LSR_BREAK 0x10
|
||||
#define LSR_THRE 0x20
|
||||
#define LSR_TEMT 0x40
|
||||
#define LSR_RXFE 0x80
|
||||
|
||||
#define TER_ENABLE 0x01
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief UART0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART0 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART0) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART1 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART1) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART1 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART2 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART2) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART2 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 driver enable switch.
|
||||
* @details If set to @p TRUE the support for UART3 is included.
|
||||
* @note The default is @p TRUE .
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_USE_UART3) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_USE_UART3 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief FIFO preload parameter.
|
||||
* @details Configuration parameter, this values defines how many bytes are
|
||||
* preloaded in the HW transmit FIFO for each interrupt, the maximum
|
||||
* value is 16 the minimum is 1.
|
||||
* @note An high value reduces the number of interrupts generated but can
|
||||
* also increase the worst case interrupt response time because the
|
||||
* preload loops.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_FIFO_PRELOAD) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_FIFO_PRELOAD 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART0_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART1_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART2 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART2_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART3 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SERIAL_UART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SERIAL_UART3_IRQ_PRIORITY 3
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
#if (LPC_SERIAL_FIFO_PRELOAD < 1) || (LPC_SERIAL_FIFO_PRELOAD > 16)
|
||||
#error "invalid LPC_SERIAL_FIFO_PRELOAD setting"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART0 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART0_PCLK LPC_BASE_UART0_CLK
|
||||
|
||||
/**
|
||||
* @brief UART1 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART1_PCLK LPC_BASE_UART1_CLK
|
||||
|
||||
/**
|
||||
* @brief UART2 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART2_PCLK LPC_BASE_UART2_CLK
|
||||
|
||||
/**
|
||||
* @brief UART3 clock.
|
||||
*/
|
||||
#define LPC_SERIAL_UART3_PCLK LPC_BASE_UART3_CLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief LPC17xx Serial Driver configuration structure.
|
||||
* @details An instance of this structure must be passed to @p sdStart()
|
||||
* in order to configure and start a serial driver operations.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Bit rate.
|
||||
*/
|
||||
uint32_t sc_speed;
|
||||
/**
|
||||
* @brief Initialization value for the LCR register.
|
||||
*/
|
||||
uint32_t sc_lcr;
|
||||
/**
|
||||
* @brief Initialization value for the FCR register.
|
||||
*/
|
||||
uint32_t sc_fcr;
|
||||
} SerialConfig;
|
||||
|
||||
/**
|
||||
* @brief @p SerialDriver specific data.
|
||||
*/
|
||||
#define _serial_driver_data \
|
||||
_base_asynchronous_channel_data \
|
||||
/* Driver state.*/ \
|
||||
sdstate_t state; \
|
||||
/* Input queue.*/ \
|
||||
InputQueue iqueue; \
|
||||
/* Output queue.*/ \
|
||||
OutputQueue oqueue; \
|
||||
/* Input circular buffer.*/ \
|
||||
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
|
||||
/* Output circular buffer.*/ \
|
||||
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
|
||||
/* End of the mandatory fields.*/ \
|
||||
/* Pointer to the USART registers block.*/ \
|
||||
LPC_USARTn_Type *uart;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD1;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD2;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD3;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART3 && !defined(__DOXYGEN__)
|
||||
extern SerialDriver SD4;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void sd_lld_init(void);
|
||||
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
|
||||
void sd_lld_stop(SerialDriver *sdp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SERIAL */
|
||||
|
||||
#endif /* _SERIAL_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,383 +1,383 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/spi_lld.c
|
||||
* @brief LPC43xx low level SPI driver code.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/** @brief SPI1 driver identifier.*/
|
||||
SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/** @brief SPI2 driver identifier.*/
|
||||
SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Preloads the transmit FIFO.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void ssp_fifo_preload(SPIDriver *spip) {
|
||||
LPC_SSPn_Type *ssp = spip->ssp;
|
||||
uint32_t n = spip->txcnt > LPC_SSP_FIFO_DEPTH ?
|
||||
LPC_SSP_FIFO_DEPTH : spip->txcnt;
|
||||
|
||||
while(((ssp->SR & SR_TNF) != 0) && (n > 0)) {
|
||||
if (spip->txptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
const uint16_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
else {
|
||||
const uint8_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
ssp->DR = 0xFFFFFFFF;
|
||||
n--;
|
||||
spip->txcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void spi_serve_interrupt(SPIDriver *spip) {
|
||||
LPC_SSPn_Type *ssp = spip->ssp;
|
||||
|
||||
if ((ssp->MIS & MIS_ROR) != 0) {
|
||||
/* The overflow condition should never happen because priority is given
|
||||
to receive but a hook macro is provided anyway...*/
|
||||
LPC_SPI_SSP_ERROR_HOOK(spip);
|
||||
}
|
||||
ssp->ICR = ICR_RT | ICR_ROR;
|
||||
while ((ssp->SR & SR_RNE) != 0) {
|
||||
if (spip->rxptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
uint16_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
else {
|
||||
uint8_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
(void)ssp->DR;
|
||||
if (--spip->rxcnt == 0) {
|
||||
chDbgAssert(spip->txcnt == 0,
|
||||
"spi_serve_interrupt(), #1", "counter out of synch");
|
||||
/* Stops the IRQ sources.*/
|
||||
ssp->IMSC = 0;
|
||||
/* Portable SPI ISR code defined in the high level driver, note, it is
|
||||
a macro.*/
|
||||
_spi_isr_code(spip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssp_fifo_preload(spip);
|
||||
if (spip->txcnt == 0)
|
||||
ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector98) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector9C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level SPI driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
#if LPC_SPI_USE_SSP0
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.ssp = LPC_SSP0;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC_SPI_USE_SSP1
|
||||
spiObjectInit(&SPID2);
|
||||
SPID2.ssp = LPC_SSP1;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_start(SPIDriver *spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CCU2->CLK_APB0_SSP0_CFG = 1;
|
||||
nvicEnableVector(SSP0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CCU2->CLK_APB2_SSP1_CFG= 1;
|
||||
nvicEnableVector(SSP1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Configuration.*/
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->ICR = ICR_RT | ICR_ROR;
|
||||
spip->ssp->CR0 = spip->config->cr0;
|
||||
spip->ssp->CPSR = spip->config->cpsr;
|
||||
spip->ssp->CR1 = CR1_SSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_stop(SPIDriver *spip) {
|
||||
|
||||
if (spip->state != SPI_STOP) {
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->CR0 = 0;
|
||||
spip->ssp->CPSR = 0;
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CCU2->CLK_APB0_SSP0_CFG = 0;
|
||||
nvicDisableVector(SSP0_IRQn);
|
||||
}
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CCU2->CLK_APB2_SSP1_CFG= 0;
|
||||
nvicDisableVector(SSP1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts the slave select signal and prepares for transfers.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_select(SPIDriver *spip) {
|
||||
|
||||
palClearPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deasserts the slave select signal.
|
||||
* @details The previously selected peripheral is unselected.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_unselect(SPIDriver *spip) {
|
||||
|
||||
palSetPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ignores data on the SPI bus.
|
||||
* @details This function transmits a series of idle words on the SPI bus and
|
||||
* ignores the received data. This function can be invoked even
|
||||
* when a slave select signal has not been yet asserted.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be ignored
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges data on the SPI bus.
|
||||
* @details This asynchronous function starts a simultaneous transmit/receive
|
||||
* operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the SPI bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from the SPI bus.
|
||||
* @details This asynchronous function starts a receive operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to receive
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges one frame using a polled wait.
|
||||
* @details This synchronous function exchanges one frame using a polled
|
||||
* synchronization method. This function is useful when exchanging
|
||||
* small amount of data on high speed channels, usually in this
|
||||
* situation is much more efficient just wait for completion using
|
||||
* polling than suspending the thread waiting for an interrupt.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] frame the data frame to send over the SPI bus
|
||||
* @return The received data frame from the SPI bus.
|
||||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
|
||||
|
||||
spip->ssp->DR = (uint32_t)frame;
|
||||
while ((spip->ssp->SR & SR_RNE) == 0)
|
||||
;
|
||||
return (uint16_t)spip->ssp->DR;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/spi_lld.c
|
||||
* @brief LPC43xx low level SPI driver code.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/** @brief SPI1 driver identifier.*/
|
||||
SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/** @brief SPI2 driver identifier.*/
|
||||
SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Preloads the transmit FIFO.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void ssp_fifo_preload(SPIDriver *spip) {
|
||||
LPC_SSPn_Type *ssp = spip->ssp;
|
||||
uint32_t n = spip->txcnt > LPC_SSP_FIFO_DEPTH ?
|
||||
LPC_SSP_FIFO_DEPTH : spip->txcnt;
|
||||
|
||||
while(((ssp->SR & SR_TNF) != 0) && (n > 0)) {
|
||||
if (spip->txptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
const uint16_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
else {
|
||||
const uint8_t *p = spip->txptr;
|
||||
ssp->DR = *p++;
|
||||
spip->txptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
ssp->DR = 0xFFFFFFFF;
|
||||
n--;
|
||||
spip->txcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*/
|
||||
static void spi_serve_interrupt(SPIDriver *spip) {
|
||||
LPC_SSPn_Type *ssp = spip->ssp;
|
||||
|
||||
if ((ssp->MIS & MIS_ROR) != 0) {
|
||||
/* The overflow condition should never happen because priority is given
|
||||
to receive but a hook macro is provided anyway...*/
|
||||
LPC_SPI_SSP_ERROR_HOOK(spip);
|
||||
}
|
||||
ssp->ICR = ICR_RT | ICR_ROR;
|
||||
while ((ssp->SR & SR_RNE) != 0) {
|
||||
if (spip->rxptr != NULL) {
|
||||
if ((ssp->CR0 & CR0_DSSMASK) > CR0_DSS8BIT) {
|
||||
uint16_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
else {
|
||||
uint8_t *p = spip->rxptr;
|
||||
*p++ = ssp->DR;
|
||||
spip->rxptr = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
(void)ssp->DR;
|
||||
if (--spip->rxcnt == 0) {
|
||||
chDbgAssert(spip->txcnt == 0,
|
||||
"spi_serve_interrupt(), #1", "counter out of synch");
|
||||
/* Stops the IRQ sources.*/
|
||||
ssp->IMSC = 0;
|
||||
/* Portable SPI ISR code defined in the high level driver, note, it is
|
||||
a macro.*/
|
||||
_spi_isr_code(spip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ssp_fifo_preload(spip);
|
||||
if (spip->txcnt == 0)
|
||||
ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_RX;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP0 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector98) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID1);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief SSP1 interrupt handler.
|
||||
*
|
||||
* @isr
|
||||
*/
|
||||
CH_IRQ_HANDLER(Vector9C) {
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
spi_serve_interrupt(&SPID2);
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level SPI driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_init(void) {
|
||||
|
||||
#if LPC_SPI_USE_SSP0
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.ssp = LPC_SSP0;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC_SPI_USE_SSP1
|
||||
spiObjectInit(&SPID2);
|
||||
SPID2.ssp = LPC_SSP1;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_start(SPIDriver *spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Clock activation.*/
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CCU2->CLK_APB0_SSP0_CFG = 1;
|
||||
nvicEnableVector(SSP0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CCU2->CLK_APB2_SSP1_CFG= 1;
|
||||
nvicEnableVector(SSP1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Configuration.*/
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->ICR = ICR_RT | ICR_ROR;
|
||||
spip->ssp->CR0 = spip->config->cr0;
|
||||
spip->ssp->CPSR = spip->config->cpsr;
|
||||
spip->ssp->CR1 = CR1_SSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the SPI peripheral.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_stop(SPIDriver *spip) {
|
||||
|
||||
if (spip->state != SPI_STOP) {
|
||||
spip->ssp->CR1 = 0;
|
||||
spip->ssp->CR0 = 0;
|
||||
spip->ssp->CPSR = 0;
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CCU2->CLK_APB0_SSP0_CFG = 0;
|
||||
nvicDisableVector(SSP0_IRQn);
|
||||
}
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CCU2->CLK_APB2_SSP1_CFG= 0;
|
||||
nvicDisableVector(SSP1_IRQn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Asserts the slave select signal and prepares for transfers.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_select(SPIDriver *spip) {
|
||||
|
||||
palClearPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deasserts the slave select signal.
|
||||
* @details The previously selected peripheral is unselected.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_unselect(SPIDriver *spip) {
|
||||
|
||||
palSetPad(spip->config->ssport, spip->config->sspad);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ignores data on the SPI bus.
|
||||
* @details This function transmits a series of idle words on the SPI bus and
|
||||
* ignores the received data. This function can be invoked even
|
||||
* when a slave select signal has not been yet asserted.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be ignored
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges data on the SPI bus.
|
||||
* @details This asynchronous function starts a simultaneous transmit/receive
|
||||
* operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to be exchanged
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends data over the SPI bus.
|
||||
* @details This asynchronous function starts a transmit operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to send
|
||||
* @param[in] txbuf the pointer to the transmit buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
|
||||
|
||||
spip->rxptr = NULL;
|
||||
spip->txptr = txbuf;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data from the SPI bus.
|
||||
* @details This asynchronous function starts a receive operation.
|
||||
* @post At the end of the operation the configured callback is invoked.
|
||||
* @note The buffers are organized as uint8_t arrays for data sizes below or
|
||||
* equal to 8 bits else it is organized as uint16_t arrays.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] n number of words to receive
|
||||
* @param[out] rxbuf the pointer to the receive buffer
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
|
||||
|
||||
spip->rxptr = rxbuf;
|
||||
spip->txptr = NULL;
|
||||
spip->rxcnt = spip->txcnt = n;
|
||||
ssp_fifo_preload(spip);
|
||||
spip->ssp->IMSC = IMSC_ROR | IMSC_RT | IMSC_TX | IMSC_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges one frame using a polled wait.
|
||||
* @details This synchronous function exchanges one frame using a polled
|
||||
* synchronization method. This function is useful when exchanging
|
||||
* small amount of data on high speed channels, usually in this
|
||||
* situation is much more efficient just wait for completion using
|
||||
* polling than suspending the thread waiting for an interrupt.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object
|
||||
* @param[in] frame the data frame to send over the SPI bus
|
||||
* @return The received data frame from the SPI bus.
|
||||
*/
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
|
||||
|
||||
spip->ssp->DR = (uint32_t)frame;
|
||||
while ((spip->ssp->SR & SR_RNE) == 0)
|
||||
;
|
||||
return (uint16_t)spip->ssp->DR;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,301 +1,301 @@
|
|||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/spi_lld.h
|
||||
* @brief LPC43xx low level SPI driver header.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SPI_LLD_H_
|
||||
#define _SPI_LLD_H_
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Hardware FIFO depth.
|
||||
*/
|
||||
#define LPC_SSP_FIFO_DEPTH 8
|
||||
|
||||
#define CR0_DSSMASK 0x0F
|
||||
#define CR0_DSS4BIT 3
|
||||
#define CR0_DSS5BIT 4
|
||||
#define CR0_DSS6BIT 5
|
||||
#define CR0_DSS7BIT 6
|
||||
#define CR0_DSS8BIT 7
|
||||
#define CR0_DSS9BIT 8
|
||||
#define CR0_DSS10BIT 9
|
||||
#define CR0_DSS11BIT 0xA
|
||||
#define CR0_DSS12BIT 0xB
|
||||
#define CR0_DSS13BIT 0xC
|
||||
#define CR0_DSS14BIT 0xD
|
||||
#define CR0_DSS15BIT 0xE
|
||||
#define CR0_DSS16BIT 0xF
|
||||
#define CR0_FRFSPI 0
|
||||
#define CR0_FRFSSI 0x10
|
||||
#define CR0_FRFMW 0x20
|
||||
#define CR0_CPOL 0x40
|
||||
#define CR0_CPHA 0x80
|
||||
#define CR0_CLOCKRATE(n) ((n) << 8)
|
||||
|
||||
#define CR1_LBM 1
|
||||
#define CR1_SSE 2
|
||||
#define CR1_MS 4
|
||||
#define CR1_SOD 8
|
||||
|
||||
#define SR_TFE 1
|
||||
#define SR_TNF 2
|
||||
#define SR_RNE 4
|
||||
#define SR_RFF 8
|
||||
#define SR_BSY 16
|
||||
|
||||
#define IMSC_ROR 1
|
||||
#define IMSC_RT 2
|
||||
#define IMSC_RX 4
|
||||
#define IMSC_TX 8
|
||||
|
||||
#define RIS_ROR 1
|
||||
#define RIS_RT 2
|
||||
#define RIS_RX 4
|
||||
#define RIS_TX 8
|
||||
|
||||
#define MIS_ROR 1
|
||||
#define MIS_RT 2
|
||||
#define MIS_RX 4
|
||||
#define MIS_TX 8
|
||||
|
||||
#define ICR_ROR 1
|
||||
#define ICR_RT 2
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief SPI1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP0 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_SPI_USE_SSP0) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_USE_SSP0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_SPI_USE_SSP1) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_USE_SSP1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP0CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP0CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP1 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP1CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP1CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP0_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overflow error hook.
|
||||
* @details The default action is to stop the system.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC_SPI_USE_SSP0 && !LPC_SPI_USE_SSP1
|
||||
#error "SPI driver activated but no SPI peripheral assigned"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 clock.
|
||||
*/
|
||||
#define LPC_SPI_SSP0_PCLK LPC_BASE_SSP0_CLK
|
||||
|
||||
/**
|
||||
* @brief SSP1 clock.
|
||||
*/
|
||||
#define LPC_SPI_SSP1_PCLK LPC_BASE_SSP1_CLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
typedef struct SPIDriver SPIDriver;
|
||||
|
||||
/**
|
||||
* @brief SPI notification callback type.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*spicallback_t)(SPIDriver *spip);
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
spicallback_t end_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief The chip select line port.
|
||||
*/
|
||||
ioportid_t ssport;
|
||||
/**
|
||||
* @brief The chip select line pad number.
|
||||
*/
|
||||
uint16_t sspad;
|
||||
/**
|
||||
* @brief SSP CR0 initialization data.
|
||||
*/
|
||||
uint16_t cr0;
|
||||
/**
|
||||
* @brief SSP CPSR initialization data.
|
||||
*/
|
||||
uint32_t cpsr;
|
||||
} SPIConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a SPI driver.
|
||||
*/
|
||||
struct SPIDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
spistate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const SPIConfig *config;
|
||||
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* SPI_USE_WAIT */
|
||||
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* SPI_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(SPI_DRIVER_EXT_FIELDS)
|
||||
SPI_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the SSP registers block.
|
||||
*/
|
||||
LPC_SSPn_Type *ssp;
|
||||
/**
|
||||
* @brief Number of bytes yet to be received.
|
||||
*/
|
||||
uint32_t rxcnt;
|
||||
/**
|
||||
* @brief Receive pointer or @p NULL.
|
||||
*/
|
||||
void *rxptr;
|
||||
/**
|
||||
* @brief Number of bytes yet to be transmitted.
|
||||
*/
|
||||
uint32_t txcnt;
|
||||
/**
|
||||
* @brief Transmit pointer or @p NULL.
|
||||
*/
|
||||
const void *txptr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_lld_init(void);
|
||||
void spi_lld_start(SPIDriver *spip);
|
||||
void spi_lld_stop(SPIDriver *spip);
|
||||
void spi_lld_select(SPIDriver *spip);
|
||||
void spi_lld_unselect(SPIDriver *spip);
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n);
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf);
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
#endif /* _SPI_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file LPC43xx/spi_lld.h
|
||||
* @brief LPC43xx low level SPI driver header.
|
||||
*
|
||||
* @addtogroup SPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SPI_LLD_H_
|
||||
#define _SPI_LLD_H_
|
||||
|
||||
#if HAL_USE_SPI || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Hardware FIFO depth.
|
||||
*/
|
||||
#define LPC_SSP_FIFO_DEPTH 8
|
||||
|
||||
#define CR0_DSSMASK 0x0F
|
||||
#define CR0_DSS4BIT 3
|
||||
#define CR0_DSS5BIT 4
|
||||
#define CR0_DSS6BIT 5
|
||||
#define CR0_DSS7BIT 6
|
||||
#define CR0_DSS8BIT 7
|
||||
#define CR0_DSS9BIT 8
|
||||
#define CR0_DSS10BIT 9
|
||||
#define CR0_DSS11BIT 0xA
|
||||
#define CR0_DSS12BIT 0xB
|
||||
#define CR0_DSS13BIT 0xC
|
||||
#define CR0_DSS14BIT 0xD
|
||||
#define CR0_DSS15BIT 0xE
|
||||
#define CR0_DSS16BIT 0xF
|
||||
#define CR0_FRFSPI 0
|
||||
#define CR0_FRFSSI 0x10
|
||||
#define CR0_FRFMW 0x20
|
||||
#define CR0_CPOL 0x40
|
||||
#define CR0_CPHA 0x80
|
||||
#define CR0_CLOCKRATE(n) ((n) << 8)
|
||||
|
||||
#define CR1_LBM 1
|
||||
#define CR1_SSE 2
|
||||
#define CR1_MS 4
|
||||
#define CR1_SOD 8
|
||||
|
||||
#define SR_TFE 1
|
||||
#define SR_TNF 2
|
||||
#define SR_RNE 4
|
||||
#define SR_RFF 8
|
||||
#define SR_BSY 16
|
||||
|
||||
#define IMSC_ROR 1
|
||||
#define IMSC_RT 2
|
||||
#define IMSC_RX 4
|
||||
#define IMSC_TX 8
|
||||
|
||||
#define RIS_ROR 1
|
||||
#define RIS_RT 2
|
||||
#define RIS_RX 4
|
||||
#define RIS_TX 8
|
||||
|
||||
#define MIS_ROR 1
|
||||
#define MIS_RT 2
|
||||
#define MIS_RX 4
|
||||
#define MIS_TX 8
|
||||
|
||||
#define ICR_ROR 1
|
||||
#define ICR_RT 2
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief SPI1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP0 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_SPI_USE_SSP0) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_USE_SSP0 TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI2 driver enable switch.
|
||||
* @details If set to @p TRUE the support for device SSP1 is included.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(LPC_SPI_USE_SSP1) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_USE_SSP1 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP0CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP0CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP1 PCLK divider.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP1CLKDIV) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP1CLKDIV 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP0_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP1_IRQ_PRIORITY 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overflow error hook.
|
||||
* @details The default action is to stop the system.
|
||||
*/
|
||||
#if !defined(LPC_SPI_SSP_ERROR_HOOK) || defined(__DOXYGEN__)
|
||||
#define LPC_SPI_SSP_ERROR_HOOK(spip) chSysHalt()
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !LPC_SPI_USE_SSP0 && !LPC_SPI_USE_SSP1
|
||||
#error "SPI driver activated but no SPI peripheral assigned"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SSP0 clock.
|
||||
*/
|
||||
#define LPC_SPI_SSP0_PCLK LPC_BASE_SSP0_CLK
|
||||
|
||||
/**
|
||||
* @brief SSP1 clock.
|
||||
*/
|
||||
#define LPC_SPI_SSP1_PCLK LPC_BASE_SSP1_CLK
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
typedef struct SPIDriver SPIDriver;
|
||||
|
||||
/**
|
||||
* @brief SPI notification callback type.
|
||||
*
|
||||
* @param[in] spip pointer to the @p SPIDriver object triggering the
|
||||
* callback
|
||||
*/
|
||||
typedef void (*spicallback_t)(SPIDriver *spip);
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Operation complete callback or @p NULL.
|
||||
*/
|
||||
spicallback_t end_cb;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief The chip select line port.
|
||||
*/
|
||||
ioportid_t ssport;
|
||||
/**
|
||||
* @brief The chip select line pad number.
|
||||
*/
|
||||
uint16_t sspad;
|
||||
/**
|
||||
* @brief SSP CR0 initialization data.
|
||||
*/
|
||||
uint16_t cr0;
|
||||
/**
|
||||
* @brief SSP CPSR initialization data.
|
||||
*/
|
||||
uint32_t cpsr;
|
||||
} SPIConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a SPI driver.
|
||||
*/
|
||||
struct SPIDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
spistate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const SPIConfig *config;
|
||||
#if SPI_USE_WAIT || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Waiting thread.
|
||||
*/
|
||||
Thread *thread;
|
||||
#endif /* SPI_USE_WAIT */
|
||||
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
Mutex mutex;
|
||||
#elif CH_USE_SEMAPHORES
|
||||
Semaphore semaphore;
|
||||
#endif
|
||||
#endif /* SPI_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(SPI_DRIVER_EXT_FIELDS)
|
||||
SPI_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the SSP registers block.
|
||||
*/
|
||||
LPC_SSPn_Type *ssp;
|
||||
/**
|
||||
* @brief Number of bytes yet to be received.
|
||||
*/
|
||||
uint32_t rxcnt;
|
||||
/**
|
||||
* @brief Receive pointer or @p NULL.
|
||||
*/
|
||||
void *rxptr;
|
||||
/**
|
||||
* @brief Number of bytes yet to be transmitted.
|
||||
*/
|
||||
uint32_t txcnt;
|
||||
/**
|
||||
* @brief Transmit pointer or @p NULL.
|
||||
*/
|
||||
const void *txptr;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID1;
|
||||
#endif
|
||||
|
||||
#if LPC_SPI_USE_SSP1 && !defined(__DOXYGEN__)
|
||||
extern SPIDriver SPID2;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_lld_init(void);
|
||||
void spi_lld_start(SPIDriver *spip);
|
||||
void spi_lld_stop(SPIDriver *spip);
|
||||
void spi_lld_select(SPIDriver *spip);
|
||||
void spi_lld_unselect(SPIDriver *spip);
|
||||
void spi_lld_ignore(SPIDriver *spip, size_t n);
|
||||
void spi_lld_exchange(SPIDriver *spip, size_t n,
|
||||
const void *txbuf, void *rxbuf);
|
||||
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
|
||||
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
|
||||
uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_SPI */
|
||||
|
||||
#endif /* _SPI_LLD_H_ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
/**********************************************************************
|
||||
* $Id$ system_lpc43xx.h 2011-06-02
|
||||
*//**
|
||||
* @file system_lpc43xx.h
|
||||
* @brief Cortex-M3 Device System Header File for NXP lpc43xx Series.
|
||||
* @version 1.0
|
||||
* @date 02. June. 2011
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __SYSTEM_lpc43xx_H
|
||||
#define __SYSTEM_lpc43xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System and update the SystemCoreClock variable.
|
||||
*/
|
||||
extern void SystemInit (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_lpc43xx_H */
|
||||
/**********************************************************************
|
||||
* $Id$ system_lpc43xx.h 2011-06-02
|
||||
*//**
|
||||
* @file system_lpc43xx.h
|
||||
* @brief Cortex-M3 Device System Header File for NXP lpc43xx Series.
|
||||
* @version 1.0
|
||||
* @date 02. June. 2011
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __SYSTEM_lpc43xx_H
|
||||
#define __SYSTEM_lpc43xx_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System and update the SystemCoreClock variable.
|
||||
*/
|
||||
extern void SystemInit (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_lpc43xx_H */
|
||||
|
|
Loading…
Reference in New Issue