mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-19 16:33:20 +08:00
修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置
This commit is contained in:
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* @brief LPC540XX ADC driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __ADC_540XX_H_
|
||||
#define __ADC_540XX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup ADC_540XX CHIP: LPC540XX A/D conversion driver
|
||||
* @ingroup CHIP_540XX_Drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Sequence index enumerations, used in various parts of the code for
|
||||
register indexing and sequencer selection */
|
||||
typedef enum {
|
||||
ADC_SEQA_IDX = 0,
|
||||
ADC_SEQB_IDX
|
||||
} ADC_SEQ_IDX_T;
|
||||
|
||||
/**
|
||||
* @brief ADC register block structure
|
||||
*/
|
||||
typedef struct { /*!< ADCn Structure */
|
||||
__IO uint32_t CTRL; // (0x00)
|
||||
__IO uint32_t INSEL; // (0x04)
|
||||
union {
|
||||
__IO uint32_t SEQ_CTRL[2]; // (0x08~0x0C)
|
||||
struct {
|
||||
__IO uint32_t SEQA_CTRL;
|
||||
__IO uint32_t SEQB_CTRL;
|
||||
};
|
||||
};
|
||||
union {
|
||||
__IO uint32_t SEQ_GDAT[2]; // (0x10~0x14)
|
||||
struct {
|
||||
__IO uint32_t SEQA_GDAT;
|
||||
__IO uint32_t SEQB_GDAT;
|
||||
};
|
||||
};
|
||||
__IO uint32_t RESERVED0[2]; // (0x18-0x1C)
|
||||
__IO uint32_t DAT[12]; // (0x20-0x4C)
|
||||
__IO uint32_t THR_LOW[2]; // (0x50~0x54)
|
||||
__IO uint32_t THR_HIGH[2]; // (0x58~0x5C)
|
||||
__IO uint32_t CHAN_THRSEL; // (0x60)
|
||||
__IO uint32_t INTEN; // (0x64)
|
||||
__IO uint32_t FLAGS; // (0x68)
|
||||
__IO uint32_t STARTUP; // (0x6C)
|
||||
__IO uint32_t CALIBR; // (0x70)
|
||||
} LPC_ADC_T;
|
||||
|
||||
/** Maximum sample rate in Hz (12-bit conversions) */
|
||||
#define ADC_MAX_SAMPLE_RATE 80000000
|
||||
#define ADC_MAX_CHANNEL_NUM 12
|
||||
|
||||
/**
|
||||
* @brief ADC register support bitfields and mask
|
||||
*/
|
||||
/** ADC Control register bit fields */
|
||||
#define ADC_CR_CLKDIV_MASK (0xFF << 0) /*!< Mask for Clock divider value */
|
||||
#define ADC_CR_CLKDIV_BITPOS (0) /*!< Bit position for Clock divider value */
|
||||
#define ADC_CR_ASYNC_MODE (1 << 8) /*!< Asynchronous mode enable bit */
|
||||
#define ADC_CR_RESOL(n) ((n) << 9) /*!< 2-bits, 6(0x0),8(0x1),10(0x2),12(0x3)-bit mode enable bit */
|
||||
#define ADC_CR_LPWRMODEBIT (1 << 10) /*!< Low power mode enable bit */
|
||||
#define ADC_CR_BYPASS (1 << 11) /*!< Bypass mode */
|
||||
#define ADC_CR_TSAMP(n) ((n) << 12) /*!< 3-bits, 2.5(0x0),3.5(0x1),4.5(0x2),5.5(0x3),6.5(0x4),7.5(0x5),8.5(0x6),9.5(0x7) ADC clocks sampling time */
|
||||
#define ADC_CR_CALMODEBIT (1 << 30) /*!< Self calibration cycle enable bit */
|
||||
#define ADC_CR_BITACC(n) ((((n) & 0x1) << 9)) /*!< 12-bit or 10-bit ADC accuracy */
|
||||
#define ADC_CR_CLKDIV(n) ((((n) & 0xFF) << 0)) /*!< The APB clock (PCLK) is divided by (this value plus one) to produce the clock for the A/D */
|
||||
#define ADC_SAMPLE_RATE_CONFIG_MASK (ADC_CR_CLKDIV(0xFF) | ADC_CR_BITACC(0x01))
|
||||
|
||||
/**
|
||||
* @brief ADC resolution bits 9 and 10
|
||||
*/
|
||||
typedef enum _ADC_RESOL_T {
|
||||
ADC_RESOL_6BIT = 0,
|
||||
ADC_RESOL_8BIT,
|
||||
ADC_RESOL_10BIT,
|
||||
ADC_RESOL_12BIT,
|
||||
} ADC_RESOL_T;
|
||||
|
||||
/**
|
||||
* @brief ADC sampling time bits 12, 13 and 14
|
||||
*/
|
||||
typedef enum _ADC_TSAMP_T {
|
||||
ADC_TSAMP_2CLK5 = 0,
|
||||
ADC_TSAMP_3CLK5,
|
||||
ADC_TSAMP_4CLK5,
|
||||
ADC_TSAMP_5CLK5,
|
||||
ADC_TSAMP_6CLK5,
|
||||
ADC_TSAMP_7CLK5,
|
||||
ADC_TSAMP_8CLK5,
|
||||
ADC_TSAMP_9CLK5,
|
||||
} ADC_TSAMP_T;
|
||||
|
||||
/* ADC input Select register */
|
||||
#define ADC_INPUTSEL_PIN (0x0<<0)
|
||||
#define ADC_INPUTSEL_CORE_VOL (0x1<<0)
|
||||
#define ADC_INPUTSEL_INTERNAL_VOL (0x2<<0)
|
||||
#define ADC_INPUTSEL_TEMP_VOL (0x3<<0)
|
||||
|
||||
/** ADC Sequence Control register bit fields */
|
||||
#define ADC_SEQ_CTRL_CHANSEL(n) (1 << (n)) /*!< Channel select macro */
|
||||
#define ADC_SEQ_CTRL_CHANSEL_BITPOS(n) ((n)<<0) /*!< Channel select macro */
|
||||
#define ADC_SEQ_CTRL_CHANSEL_MASK (0xFFF) /*!< Channel select mask */
|
||||
|
||||
/** SEQ_CTRL register bit fields */
|
||||
#define ADC_SEQ_CTRL_TRIGGER(n) ((n)<<12)
|
||||
#define ADC_SEQ_CTRL_HWTRIG_POLPOS (1 << 18) /*!< HW trigger polarity - positive edge */
|
||||
#define ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS (1 << 19) /*!< HW trigger bypass synchronisation */
|
||||
#define ADC_SEQ_CTRL_START (1 << 26) /*!< Start conversion enable bit */
|
||||
#define ADC_SEQ_CTRL_BURST (1 << 27) /*!< Repeated conversion enable bit */
|
||||
#define ADC_SEQ_CTRL_SINGLESTEP (1 << 28) /*!< Single step enable bit */
|
||||
#define ADC_SEQ_CTRL_LOWPRIO (1 << 29) /*!< High priority enable bit (regardless of name) */
|
||||
#define ADC_SEQ_CTRL_MODE_EOS (1 << 30) /*!< Mode End of sequence enable bit */
|
||||
#define ADC_SEQ_CTRL_SEQ_ENA (1UL << 31) /*!< Sequence enable bit */
|
||||
|
||||
/** ADC global data register bit fields */
|
||||
#define ADC_SEQ_GDAT_RESULT_MASK (0xFFF << 4) /*!< Result value mask */
|
||||
#define ADC_SEQ_GDAT_RESULT_BITPOS (4) /*!< Result start bit position */
|
||||
#define ADC_SEQ_GDAT_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */
|
||||
#define ADC_SEQ_GDAT_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */
|
||||
#define ADC_SEQ_GDAT_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */
|
||||
#define ADC_SEQ_GDAT_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */
|
||||
#define ADC_SEQ_GDAT_CHAN_MASK (0xF << 26) /*!< Channel number mask */
|
||||
#define ADC_SEQ_GDAT_CHAN_BITPOS (26) /*!< Channel number bit position */
|
||||
#define ADC_SEQ_GDAT_OVERRUN (1 << 30) /*!< Overrun bit */
|
||||
#define ADC_SEQ_GDAT_DATAVALID (1UL << 31) /*!< Data valid bit */
|
||||
|
||||
/** ADC Data register bit fields */
|
||||
#define ADC_DR_RESULT_BITPOS (4) /*!< Result start bit position */
|
||||
#define ADC_DR_RESULT(n) ((((n) >> 4) & 0xFFF)) /*!< Macro for getting the ADC data value */
|
||||
#define ADC_DR_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */
|
||||
#define ADC_DR_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */
|
||||
#define ADC_DR_THCMPRANGE(n) (((n) >> ADC_DR_THCMPRANGE_BITPOS) & 0x3)
|
||||
#define ADC_DR_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */
|
||||
#define ADC_DR_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */
|
||||
#define ADC_DR_THCMPCROSS(n) (((n) >> ADC_DR_THCMPCROSS_BITPOS) & 0x3)
|
||||
#define ADC_DR_CHAN_MASK (0xF << 26) /*!< Channel number mask */
|
||||
#define ADC_DR_CHAN_BITPOS (26) /*!< Channel number bit position */
|
||||
#define ADC_DR_CHANNEL(n) (((n) >> ADC_DR_CHAN_BITPOS) & 0xF) /*!< Channel number bit position */
|
||||
#define ADC_DR_OVERRUN (1 << 30) /*!< Overrun bit */
|
||||
#define ADC_DR_DATAVALID (1UL << 31) /*!< Data valid bit */
|
||||
#define ADC_DR_DONE(n) (((n) >> 31))
|
||||
|
||||
/** ADC low/high Threshold register bit fields */
|
||||
#define ADC_THR_VAL_MASK (0xFFF << 4) /*!< Threshold value bit mask */
|
||||
#define ADC_THR_VAL_POS (4) /*!< Threshold value bit position */
|
||||
|
||||
/** ADC Threshold select register bit fields */
|
||||
#define ADC_THRSEL_CHAN_SEL_THR1(n) (1 << (n)) /*!< Select THR1 register for channel n */
|
||||
|
||||
/** ADC Interrupt Enable register bit fields */
|
||||
#define ADC_INTEN_SEQA_ENABLE (1 << 0) /*!< Sequence A Interrupt enable bit */
|
||||
#define ADC_INTEN_SEQB_ENABLE (1 << 1) /*!< Sequence B Interrupt enable bit */
|
||||
#define ADC_INTEN_SEQN_ENABLE(seq) (1 << (seq)) /*!< Sequence A/B Interrupt enable bit */
|
||||
#define ADC_INTEN_OVRRUN_ENABLE (1 << 2) /*!< Overrun Interrupt enable bit */
|
||||
#define ADC_INTEN_CMP_DISBALE (0) /*!< Disable comparison interrupt value */
|
||||
#define ADC_INTEN_CMP_OUTSIDETH (1) /*!< Outside threshold interrupt value */
|
||||
#define ADC_INTEN_CMP_CROSSTH (2) /*!< Crossing threshold interrupt value */
|
||||
#define ADC_INTEN_CMP_MASK (3) /*!< Comparison interrupt value mask */
|
||||
#define ADC_INTEN_CMP_ENABLE(isel, ch) (((isel) & ADC_INTEN_CMP_MASK) << ((2 * (ch)) + 3)) /*!< Interrupt selection for channel */
|
||||
|
||||
/** ADC Flags register bit fields */
|
||||
#define ADC_FLAGS_THCMP_MASK(ch) (1 << (ch)) /*!< Threshold comparison status for channel */
|
||||
#define ADC_FLAGS_OVRRUN_MASK(ch) (1 << (12 + (ch))) /*!< Overrun status for channel */
|
||||
#define ADC_FLAGS_SEQA_OVRRUN_MASK (1 << 24) /*!< Seq A Overrun status */
|
||||
#define ADC_FLAGS_SEQB_OVRRUN_MASK (1 << 25) /*!< Seq B Overrun status */
|
||||
#define ADC_FLAGS_SEQN_OVRRUN_MASK(seq) (1 << (24 + (seq))) /*!< Seq A/B Overrun status */
|
||||
#define ADC_FLAGS_SEQA_INT_MASK (1 << 28) /*!< Seq A Interrupt status */
|
||||
#define ADC_FLAGS_SEQB_INT_MASK (1 << 29) /*!< Seq B Interrupt status */
|
||||
#define ADC_FLAGS_SEQN_INT_MASK(seq) (1 << (28 + (seq)))/*!< Seq A/B Interrupt status */
|
||||
#define ADC_FLAGS_THCMP_INT_MASK (1 << 30) /*!< Threshold comparison Interrupt status */
|
||||
#define ADC_FLAGS_OVRRUN_INT_MASK (1UL << 31) /*!< Overrun Interrupt status */
|
||||
|
||||
/** ADC Startup register bit fields */
|
||||
#define ADC_STARTUP_ENABLE (0x1 << 0)
|
||||
#define ADC_STARTUP_INIT (0x1 << 1)
|
||||
|
||||
/* ADC Calibration register definition */
|
||||
#define ADC_CALIB (0x1<<0)
|
||||
#define ADC_CALREQD (0x1<<1)
|
||||
|
||||
/**
|
||||
* @brief Initialize the ADC peripheral
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param flags : ADC flags for init (ADC_CR_MODE10BIT and/or ADC_CR_LPWRMODEBIT)
|
||||
* @return Nothing
|
||||
* @note To select low-power ADC mode, enable the ADC_CR_LPWRMODEBIT flag.
|
||||
* To select 10-bit conversion mode, enable the ADC_CR_MODE10BIT flag.<br>
|
||||
* Example: Chip_ADC_Init(LPC_ADC, (ADC_CR_MODE10BIT | ADC_CR_LPWRMODEBIT));
|
||||
*/
|
||||
void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags);
|
||||
|
||||
/**
|
||||
* @brief Shutdown ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note Disables the ADC clocks and ADC power
|
||||
*/
|
||||
void Chip_ADC_DeInit(LPC_ADC_T *pADC);
|
||||
|
||||
/**
|
||||
* @brief Set ADC divider
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param div : ADC divider value to set minus 1
|
||||
* @return Nothing
|
||||
* @note The value is used as a divider to generate the ADC
|
||||
* clock rate from the ADC input clock. The ADC input clock is based
|
||||
* on the system clock. Valid values for this function are from 0 to 255
|
||||
* with 0=divide by 1, 1=divide by 2, 2=divide by 3, etc.<br>
|
||||
* Do not decrement this value by 1.<br>
|
||||
* To set the ADC clock rate to 1MHz, use the following function:<br>
|
||||
* Chip_ADC_SetDivider(LPC_ADC, (Chip_Clock_GetSystemClockRate() / 1000000) - 1);
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_SetDivider(LPC_ADC_T *pADC, uint8_t div)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
temp = pADC->CTRL & ~(ADC_CR_CLKDIV_MASK);
|
||||
pADC->CTRL = temp | (uint32_t) div;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ADC clock rate
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param rate : rate in Hz to set ADC clock to (maximum ADC_MAX_SAMPLE_RATE)
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief Get ADC divider
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @return the current ADC divider
|
||||
* @note This function returns the divider that is used to generate the
|
||||
* ADC frequency. The returned value must be incremented by 1. The
|
||||
* frequency can be determined with the following function:<br>
|
||||
* adc_freq = Chip_Clock_GetSystemClockRate() / (Chip_ADC_GetDivider(LPC_ADC) + 1);
|
||||
*/
|
||||
STATIC INLINE uint8_t Chip_ADC_GetDivider(LPC_ADC_T *pADC)
|
||||
{
|
||||
return pADC->CTRL & ADC_CR_CLKDIV_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start ADC calibration
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note Calibration is not done as part of Chip_ADC_Init(), but
|
||||
* is required after the call to Chip_ADC_Init() or after returning
|
||||
* from a power-down state.
|
||||
*/
|
||||
void Chip_ADC_StartCalibration(LPC_ADC_T *pADC);
|
||||
|
||||
/**
|
||||
* @brief Helper function for safely setting ADC sequencer register bits
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to set bits for
|
||||
* @param bits : Or'ed bits of a sequencer register to set
|
||||
* @return Nothing
|
||||
* @note This function will safely set the ADC sequencer register bits
|
||||
* while maintaining bits 20..25 as 0, regardless of the read state of those bits.
|
||||
*/
|
||||
void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Helper function for safely clearing ADC sequencer register bits
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to clear bits for
|
||||
* @param bits : Or'ed bits of a sequencer register to clear
|
||||
* @return Nothing
|
||||
* @note This function will safely clear the ADC sequencer register bits
|
||||
* while maintaining bits 20..25 as 0, regardless of the read state of those bits.
|
||||
*/
|
||||
void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Sets up ADC conversion sequencer A or B
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to setup
|
||||
* @param options : OR'ed Sequencer options to setup (see notes)
|
||||
* @return Nothing
|
||||
* @note Sets up sequencer options for a conversion sequence. This function
|
||||
* should be used to setup the selected channels for the sequence, the sequencer
|
||||
* trigger, the trigger polarity, synchronization bypass, priority, and mode. All
|
||||
* options are passed to the functions as a OR'ed list of values. This function will
|
||||
* disable/clear the sequencer start/burst/single step/enable if they are enabled.<br>
|
||||
* Select the channels by OR'ing in one or more ADC_SEQ_CTRL_CHANSEL(ch) values.<br>
|
||||
* Select the hardware trigger by OR'ing in one ADC_SEQ_CTRL_HWTRIG_* value.<br>
|
||||
* Select a positive edge hardware trigger by OR'ing in ADC_SEQ_CTRL_HWTRIG_POLPOS.<br>
|
||||
* Select trigger bypass synchronisation by OR'ing in ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS.<br>
|
||||
* Select ADC single step on trigger/start by OR'ing in ADC_SEQ_CTRL_SINGLESTEP.<br>
|
||||
* Select higher priority conversion on the other sequencer by OR'ing in ADC_SEQ_CTRL_LOWPRIO.<br>
|
||||
* Select end of seqeuence instead of end of conversion interrupt by OR'ing in ADC_SEQ_CTRL_MODE_EOS.<br>
|
||||
* Example for setting up sequencer A (channels 0-2, trigger on high edge of PIO0_2, interrupt on end of sequence):<br>
|
||||
* Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX, (
|
||||
* ADC_SEQ_CTRL_CHANSEL(0) | ADC_SEQ_CTRL_CHANSEL(1) | ADC_SEQ_CTRL_CHANSEL(2) |
|
||||
* ADC_SEQ_CTRL_HWTRIG_PIO0_2 | ADC_SEQ_CTRL_HWTRIG_POLPOS | ADC_SEQ_CTRL_MODE_EOS));
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_SetupSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t options)
|
||||
{
|
||||
pADC->SEQ_CTRL[seqIndex] = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sequenceX control register value
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @return seq_ctrl : sequenceX_control register value
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_ADC_GetSequencerCtrl(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
return ( pADC->SEQ_CTRL[seqIndex] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a sequencer
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to enable
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_EnableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables a sequencer
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to disable
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_DisableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Forces a sequencer trigger event (software trigger of ADC)
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to start
|
||||
* @return Nothing
|
||||
* @note This function sets the START bit for the sequencer to force a
|
||||
* single conversion sequence or a single step conversion. START and BURST bits can not
|
||||
* be set at the same time, thus, BURST bit will be cleared.
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_StartSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST);
|
||||
Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_START);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts sequencer burst mode
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to start burst on
|
||||
* @return Nothing
|
||||
* @note This function sets the BURST bit for the sequencer to force
|
||||
* continuous conversion. Use Chip_ADC_StopBurstSequencer() to stop the
|
||||
* ADC burst sequence. START and BURST bits can not be set at the same time, thus,
|
||||
* START bit will be cleared.
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_StartBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
/* START and BURST bits can not be set at the same time. */
|
||||
Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_START);
|
||||
Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops sequencer burst mode
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to stop burst on
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_StopBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST);
|
||||
}
|
||||
|
||||
/** ADC sequence global data register threshold comparison range enumerations */
|
||||
typedef enum {
|
||||
ADC_DR_THCMPRANGE_INRANGE,
|
||||
ADC_DR_THCMPRANGE_RESERVED,
|
||||
ADC_DR_THCMPRANGE_BELOW,
|
||||
ADC_DR_THCMPRANGE_ABOVE
|
||||
} ADC_DR_THCMPRANGE_T;
|
||||
|
||||
/** ADC sequence global data register threshold comparison cross enumerations */
|
||||
typedef enum {
|
||||
ADC_DR_THCMPCROSS_NOCROSS,
|
||||
ADC_DR_THCMPCROSS_RESERVED,
|
||||
ADC_DR_THCMPCROSS_DOWNWARD,
|
||||
ADC_DR_THCMPCROSS_UPWARD
|
||||
} ADC_DR_THCMPCROSS_T;
|
||||
|
||||
/**
|
||||
* @brief Read a ADC sequence global data register
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param seqIndex : Sequencer to read
|
||||
* @return Current raw value of the ADC sequence A or B global data register
|
||||
* @note This function returns the raw value of the data register and clears
|
||||
* the overrun and datavalid status for the register. Once this register is read,
|
||||
* the following functions can be used to parse the raw value:<br>
|
||||
* uint32_t adcDataRawValue = Chip_ADC_GetGlobalDataReg(LPC_ADC, ADC_SEQA_IDX); // Get raw value
|
||||
* uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value
|
||||
* ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high
|
||||
* ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low
|
||||
* uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data
|
||||
* bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag
|
||||
* bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_ADC_GetGlobalDataReg(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
|
||||
{
|
||||
return pADC->SEQ_GDAT[seqIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a ADC data register
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param index : Data register to read, 0-11
|
||||
* @return Current raw value of the ADC data register
|
||||
* @note This function returns the raw value of the data register and clears
|
||||
* the overrun and datavalid status for the register. Once this register is read,
|
||||
* the following functions can be used to parse the raw value:<br>
|
||||
* uint32_t adcDataRawValue = Chip_ADC_GetDataReg(LPC_ADC, ADC_MAX_CHANNEL_NUM); // Get raw value
|
||||
* uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value
|
||||
* ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high
|
||||
* ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low
|
||||
* uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data
|
||||
* bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag
|
||||
* bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_ADC_GetDataReg(LPC_ADC_T *pADC, uint8_t index)
|
||||
{
|
||||
return pADC->DAT[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Threshold low value in ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0)
|
||||
* @param value : Threshold low data value (should be 12-bit value)
|
||||
* @return None
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_SetThrLowValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value)
|
||||
{
|
||||
pADC->THR_LOW[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Threshold high value in ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0)
|
||||
* @param value : Threshold high data value (should be 12-bit value)
|
||||
* @return None
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_SetThrHighValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value)
|
||||
{
|
||||
pADC->THR_HIGH[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Select threshold 0 values for comparison for selected channels
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values
|
||||
* @return None
|
||||
* @note Select multiple channels to use the threshold 0 comparison.<br>
|
||||
* Example:<br>
|
||||
* Chip_ADC_SelectTH0Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(1) | ADC_THRSEL_CHAN_SEL_THR1(2))); // Selects channels 1 and 2 for threshold 0
|
||||
*/
|
||||
void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels);
|
||||
|
||||
/**
|
||||
* @brief Select threshold 1 value for comparison for selected channels
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values
|
||||
* @return None
|
||||
* @note Select multiple channels to use the 1 threshold comparison.<br>
|
||||
* Example:<br>
|
||||
* Chip_ADC_SelectTH1Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(4) | ADC_THRSEL_CHAN_SEL_THR1(5))); // Selects channels 4 and 5 for 1 threshold
|
||||
*/
|
||||
void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels);
|
||||
|
||||
/**
|
||||
* @brief Enable interrupts in ADC (sequencers A/B and overrun)
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param intMask : Interrupt values to be enabled (see notes)
|
||||
* @return None
|
||||
* @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE,
|
||||
* ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to enable the
|
||||
* specific ADC interrupts.
|
||||
*/
|
||||
void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask);
|
||||
|
||||
/**
|
||||
* @brief Disable interrupts in ADC (sequencers A/B and overrun)
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param intMask : Interrupt values to be disabled (see notes)
|
||||
* @return None
|
||||
* @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE,
|
||||
* ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to disable the
|
||||
* specific ADC interrupts.
|
||||
*/
|
||||
void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask);
|
||||
|
||||
/** Threshold interrupt event options */
|
||||
typedef enum {
|
||||
ADC_INTEN_THCMP_DISABLE,
|
||||
ADC_INTEN_THCMP_OUTSIDE,
|
||||
ADC_INTEN_THCMP_CROSSING,
|
||||
} ADC_INTEN_THCMP_T;
|
||||
|
||||
/**
|
||||
* @brief Enable a threshold event interrupt in ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param ch : ADC channel to set threshold inetrrupt for, 1-8
|
||||
* @param thInt : Selected threshold interrupt type
|
||||
* @return None
|
||||
*/
|
||||
void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt);
|
||||
|
||||
/**
|
||||
* @brief Get flags register in ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @return Flags register value (ORed ADC_FLAG* values)
|
||||
* @note Mask the return value of this function with the ADC_FLAGS_*
|
||||
* definitions to determine the overall ADC interrupt events.<br>
|
||||
* Example:<br>
|
||||
* if (Chip_ADC_GetFlags(LPC_ADC) & ADC_FLAGS_THCMP_MASK(3) // Check of threshold comp status for ADC channel 3
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_ADC_GetFlags(LPC_ADC_T *pADC)
|
||||
{
|
||||
return pADC->FLAGS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear flags register in ADC
|
||||
* @param pADC : The base of ADC peripheral on the chip
|
||||
* @param flags : An Or'ed values of ADC_FLAGS_* values to clear
|
||||
* @return Flags register value (ORed ADC_FLAG* values)
|
||||
*/
|
||||
STATIC INLINE void Chip_ADC_ClearFlags(LPC_ADC_T *pADC, uint32_t flags)
|
||||
{
|
||||
pADC->FLAGS = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ADC_540XX_H_ */
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* @brief LPC540XX ADC driver (clock enable/disable only)
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Set ADC interrupt bits (safe) */
|
||||
void Chip_ADC_SetIntBits(LPC_ADC_T *pADC, uint32_t intMask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to undefined bits */
|
||||
temp = pADC->INTEN & 0x07FFFFFF;
|
||||
pADC->INTEN = temp | intMask;
|
||||
}
|
||||
|
||||
/* Clear ADC interrupt bits (safe) */
|
||||
void Chip_ADC_ClearIntBits(LPC_ADC_T *pADC, uint32_t intMask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to undefined bits */
|
||||
temp = pADC->INTEN & 0x07FFFFFF;
|
||||
pADC->INTEN = temp & ~intMask;
|
||||
}
|
||||
|
||||
/* Set ADC threshold selection bits (safe) */
|
||||
void Chip_ADC_SetTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to undefined bits */
|
||||
temp = pADC->CHAN_THRSEL & 0x00000FFF;
|
||||
pADC->CHAN_THRSEL = temp | mask;
|
||||
}
|
||||
|
||||
/* Clear ADC threshold selection bits (safe) */
|
||||
void Chip_ADC_ClearTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to undefined bits */
|
||||
temp = pADC->CHAN_THRSEL & 0x00000FFF;
|
||||
pADC->CHAN_THRSEL = temp & ~mask;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Initialize the ADC peripheral */
|
||||
void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags)
|
||||
{
|
||||
/* Power up ADC and enable ADC base clock */
|
||||
Chip_SYSCON_PowerUp(SYSCON_PDRUNCFG_PD_ADC0 | SYSCON_PDRUNCFG_PD_VDDA_ENA | SYSCON_PDRUNCFG_PD_VREFP);
|
||||
Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_ADC0);
|
||||
|
||||
/* Disable ADC interrupts */
|
||||
pADC->INTEN = 0;
|
||||
|
||||
/* Set ADC control options */
|
||||
pADC->CTRL = flags;
|
||||
}
|
||||
|
||||
/* Shutdown ADC */
|
||||
void Chip_ADC_DeInit(LPC_ADC_T *pADC)
|
||||
{
|
||||
pADC->INTEN = 0;
|
||||
pADC->CTRL = 0;
|
||||
|
||||
/* Stop ADC clock and then power down ADC */
|
||||
Chip_Clock_DisablePeriphClock(SYSCON_CLOCK_ADC0);
|
||||
Chip_SYSCON_PowerDown(SYSCON_PDRUNCFG_PD_ADC0 | SYSCON_PDRUNCFG_PD_VDDA_ENA | SYSCON_PDRUNCFG_PD_VREFP);
|
||||
}
|
||||
|
||||
/* Start ADC calibration */
|
||||
void Chip_ADC_StartCalibration(LPC_ADC_T *pADC)
|
||||
{
|
||||
/* Set calibration mode */
|
||||
pADC->CTRL |= ADC_CR_CALMODEBIT;
|
||||
|
||||
/* Clear ASYNC bit */
|
||||
pADC->CTRL &= ~ADC_CR_ASYNC_MODE;
|
||||
|
||||
/* Setup ADC for about 500KHz (per UM) */
|
||||
Chip_ADC_SetClockRate(pADC, 500000);
|
||||
|
||||
/* Clearn low power bit */
|
||||
pADC->CTRL &= ~ADC_CR_LPWRMODEBIT;
|
||||
|
||||
/* Calibration is only complete when ADC_CR_CALMODEBIT bit has cleared */
|
||||
}
|
||||
|
||||
/* Set ADC clock rate */
|
||||
void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate)
|
||||
{
|
||||
uint32_t div;
|
||||
|
||||
/* Get ADC clock source to determine base ADC rate. IN sychronous mode,
|
||||
the ADC base clock comes from the system clock. In ASYNC mode, it
|
||||
comes from the ASYNC ADC clock and this function doesn't work. */
|
||||
div = Chip_Clock_GetSystemClockRate() / rate;
|
||||
if (div == 0) {
|
||||
div = 1;
|
||||
}
|
||||
|
||||
Chip_ADC_SetDivider(pADC, (uint8_t) div - 1);
|
||||
}
|
||||
|
||||
/* Helper function for safely setting ADC sequencer register bits */
|
||||
void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read sequencer register and mask off bits 20..25 */
|
||||
temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
|
||||
|
||||
/* OR in passed bits */
|
||||
pADC->SEQ_CTRL[seqIndex] = temp | bits;
|
||||
}
|
||||
|
||||
/* Helper function for safely clearing ADC sequencer register bits */
|
||||
void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read sequencer register and mask off bits 20..25 */
|
||||
temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
|
||||
|
||||
/* OR in passed bits */
|
||||
pADC->SEQ_CTRL[seqIndex] = temp & ~bits;
|
||||
}
|
||||
|
||||
/* Enable interrupts in ADC (sequencers A/B and overrun) */
|
||||
void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask)
|
||||
{
|
||||
Chip_ADC_SetIntBits(pADC, intMask);
|
||||
}
|
||||
|
||||
/* Disable interrupts in ADC (sequencers A/B and overrun) */
|
||||
void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask)
|
||||
{
|
||||
Chip_ADC_ClearIntBits(pADC, intMask);
|
||||
}
|
||||
|
||||
/* Enable a threshold event interrupt in ADC */
|
||||
void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt)
|
||||
{
|
||||
int shiftIndex = 3 + (ch * 2);
|
||||
|
||||
/* Clear current bits first */
|
||||
Chip_ADC_ClearIntBits(pADC, (ADC_INTEN_CMP_MASK << shiftIndex));
|
||||
|
||||
/* Set new threshold interrupt type */
|
||||
Chip_ADC_SetIntBits(pADC, ((uint32_t) thInt << shiftIndex));
|
||||
}
|
||||
|
||||
/* Select threshold 0 values for comparison for selected channels */
|
||||
void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels)
|
||||
{
|
||||
Chip_ADC_ClearTHRSELBits(pADC, channels);
|
||||
}
|
||||
|
||||
/* Select threshold 1 value for comparison for selected channels */
|
||||
void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels)
|
||||
{
|
||||
Chip_ADC_SetTHRSELBits(pADC, channels);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* @brief LPC540XX DMA chip driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2013
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase()
|
||||
function if a DMA SRAM table is needed. This table is correctly aligned for
|
||||
the DMA controller. */
|
||||
#if defined(__CC_ARM)
|
||||
/* Keil alignement to 512 bytes */
|
||||
__align(512) DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
|
||||
#endif /* defined (__CC_ARM) */
|
||||
|
||||
/* IAR support */
|
||||
#if defined(__ICCARM__)
|
||||
/* IAR EWARM alignement to 512 bytes */
|
||||
#pragma data_alignment=512
|
||||
DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
|
||||
#endif /* defined (__ICCARM__) */
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
/* GNU alignement to 512 bytes */
|
||||
DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL] __attribute__ ((aligned(512)));
|
||||
#endif /* defined (__GNUC__) */
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Set DMA transfer register interrupt bits (safe) */
|
||||
void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to
|
||||
undefined bits */
|
||||
temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0;
|
||||
|
||||
pDMA->DMACH[ch].XFERCFG = temp | mask;
|
||||
}
|
||||
|
||||
/* Clear DMA transfer register interrupt bits (safe) */
|
||||
void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
/* Read and write values may not be the same, write 0 to
|
||||
undefined bits */
|
||||
temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0;
|
||||
|
||||
pDMA->DMACH[ch].XFERCFG = temp & ~mask;
|
||||
}
|
||||
|
||||
/* Update the transfer size in an existing DMA channel transfer configuration */
|
||||
void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans)
|
||||
{
|
||||
Chip_DMA_ClearTranBits(pDMA, ch, (0x3FF << 16));
|
||||
Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_XFERCOUNT(trans));
|
||||
}
|
||||
|
||||
/* Sets up a DMA channel with the passed DMA transfer descriptor */
|
||||
bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc)
|
||||
{
|
||||
bool good = false;
|
||||
DMA_CHDESC_T *pDesc = (DMA_CHDESC_T *) pDMA->SRAMBASE;
|
||||
|
||||
if ((Chip_DMA_GetActiveChannels(pDMA) & (1 << ch)) == 0) {
|
||||
/* Channel is not active, so update the descriptor */
|
||||
pDesc[ch] = *desc;
|
||||
|
||||
good = true;
|
||||
}
|
||||
|
||||
return good;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize DMA parameters specific to a channel
|
||||
*
|
||||
* @param channel
|
||||
* @param src_address
|
||||
* @param dst_address
|
||||
* @param xfr_width
|
||||
* @param length_bytes
|
||||
*/
|
||||
void Chip_DMA_InitChannel( DMA_CHID_T channel, uint32_t src_address, uint32_t src_increment,
|
||||
uint32_t dst_address, uint32_t dst_increment, uint32_t xfr_width, uint32_t length_bytes, uint32_t priority)
|
||||
{
|
||||
Chip_DMA_EnableChannel(LPC_DMA, channel);
|
||||
Chip_DMA_EnableIntChannel(LPC_DMA, channel);
|
||||
|
||||
Chip_DMA_SetupChannelConfig(LPC_DMA, channel, DMA_CFG_PERIPHREQEN |
|
||||
DMA_CFG_CHPRIORITY(priority));
|
||||
|
||||
if (src_increment != DMA_XFERCFG_SRCINC_0) {
|
||||
Chip_DMA_Table[channel].source = DMA_ADDR((src_address + length_bytes)
|
||||
- (1UL << xfr_width));
|
||||
} else {
|
||||
Chip_DMA_Table[channel].source = DMA_ADDR(src_address);
|
||||
}
|
||||
|
||||
if (dst_increment != DMA_XFERCFG_DSTINC_0) {
|
||||
Chip_DMA_Table[channel].dest = DMA_ADDR((dst_address + length_bytes)
|
||||
- (1UL << xfr_width));
|
||||
} else {
|
||||
Chip_DMA_Table[channel].dest = DMA_ADDR(dst_address);
|
||||
}
|
||||
Chip_DMA_Table[channel].next = DMA_ADDR(0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the DMA transfer
|
||||
*
|
||||
* @param channel
|
||||
* @param src_increment
|
||||
* @param dst_increment
|
||||
* @param xfr_width
|
||||
* @param length_bytes
|
||||
*/
|
||||
void Chip_DMA_StartTransfer(DMA_CHID_T channel, uint32_t src_increment, uint32_t dst_increment, uint32_t xfr_width, uint32_t length_bytes)
|
||||
{
|
||||
uint32_t xfer_count;
|
||||
|
||||
/* Calculate transfer_count ( length in terms of transfers) */
|
||||
xfer_count = (xfr_width == DMA_XFERCFG_WIDTH_8) ? length_bytes :
|
||||
(xfr_width == DMA_XFERCFG_WIDTH_16) ? (length_bytes >> 1) :
|
||||
(length_bytes >> 2);
|
||||
|
||||
Chip_DMA_SetupChannelTransfer(LPC_DMA, channel,
|
||||
(DMA_XFERCFG_CFGVALID | DMA_XFERCFG_SETINTA | DMA_XFERCFG_SWTRIG |
|
||||
xfr_width | src_increment | dst_increment |
|
||||
DMA_XFERCFG_XFERCOUNT(xfer_count)));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* @brief LPC540XX Cyclic Redundancy Check (CRC) Engine driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __DMA_540XX_H
|
||||
#define __DMA_540XX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup DMA_540XX CHIP: LPC540XX DMA Engine driver
|
||||
* @ingroup CHIP_540XX_Drivers
|
||||
* @{
|
||||
*/
|
||||
/** @defgroup DMA_11U6X CHIP: LPC11u6x DMA Controller driver
|
||||
* @ingroup CHIP_11U6X_Drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA Controller shared registers structure
|
||||
*/
|
||||
typedef struct { /*!< DMA shared registers structure */
|
||||
__IO uint32_t ENABLESET; /*!< DMA Channel Enable read and Set for all DMA channels */
|
||||
__I uint32_t RESERVED0;
|
||||
__O uint32_t ENABLECLR; /*!< DMA Channel Enable Clear for all DMA channels */
|
||||
__I uint32_t RESERVED1;
|
||||
__I uint32_t ACTIVE; /*!< DMA Channel Active status for all DMA channels */
|
||||
__I uint32_t RESERVED2;
|
||||
__I uint32_t BUSY; /*!< DMA Channel Busy status for all DMA channels */
|
||||
__I uint32_t RESERVED3;
|
||||
__IO uint32_t ERRINT; /*!< DMA Error Interrupt status for all DMA channels */
|
||||
__I uint32_t RESERVED4;
|
||||
__IO uint32_t INTENSET; /*!< DMA Interrupt Enable read and Set for all DMA channels */
|
||||
__I uint32_t RESERVED5;
|
||||
__O uint32_t INTENCLR; /*!< DMA Interrupt Enable Clear for all DMA channels */
|
||||
__I uint32_t RESERVED6;
|
||||
__IO uint32_t INTA; /*!< DMA Interrupt A status for all DMA channels */
|
||||
__I uint32_t RESERVED7;
|
||||
__IO uint32_t INTB; /*!< DMA Interrupt B status for all DMA channels */
|
||||
__I uint32_t RESERVED8;
|
||||
__O uint32_t SETVALID; /*!< DMA Set ValidPending control bits for all DMA channels */
|
||||
__I uint32_t RESERVED9;
|
||||
__O uint32_t SETTRIG; /*!< DMA Set Trigger control bits for all DMA channels */
|
||||
__I uint32_t RESERVED10;
|
||||
__O uint32_t ABORT; /*!< DMA Channel Abort control for all DMA channels */
|
||||
} LPC_DMA_COMMON_T;
|
||||
|
||||
/**
|
||||
* @brief DMA Controller shared registers structure
|
||||
*/
|
||||
typedef struct { /*!< DMA channel register structure */
|
||||
__IO uint32_t CFG; /*!< DMA Configuration register */
|
||||
__I uint32_t CTLSTAT; /*!< DMA Control and status register */
|
||||
__IO uint32_t XFERCFG; /*!< DMA Transfer configuration register */
|
||||
__I uint32_t RESERVED;
|
||||
} LPC_DMA_CHANNEL_T;
|
||||
|
||||
/* DMA channel mapping - each channel is mapped to an individual peripheral
|
||||
and direction or a DMA imput mux trigger */
|
||||
typedef enum {
|
||||
DMAREQ_UART0_RX = 0, /*!< UART00 receive DMA channel */
|
||||
DMA_CH0 = DMAREQ_UART0_RX,
|
||||
DMAREQ_UART0_TX, /*!< UART0 transmit DMA channel */
|
||||
DMA_CH1 = DMAREQ_UART0_TX,
|
||||
DMAREQ_UART1_RX, /*!< UART1 receive DMA channel */
|
||||
DMA_CH2 = DMAREQ_UART1_RX,
|
||||
DMAREQ_UART1_TX, /*!< UART1 transmit DMA channel */
|
||||
DMA_CH3 = DMAREQ_UART1_TX,
|
||||
DMAREQ_UART2_RX, /*!< UART2 receive DMA channel */
|
||||
DMA_CH4 = DMAREQ_UART2_RX,
|
||||
DMAREQ_UART2_TX, /*!< UART2 transmit DMA channel */
|
||||
DMA_CH5 = DMAREQ_UART2_TX,
|
||||
DMAREQ_UART3_RX, /*!< UART3 receive DMA channel */
|
||||
DMA_CH6 = DMAREQ_UART3_RX,
|
||||
DMAREQ_UART3_TX, /*!< UART3 transmit DMA channel */
|
||||
DMA_CH7 = DMAREQ_UART3_TX,
|
||||
DMAREQ_SPI0_RX, /*!< SPI0 receive DMA channel */
|
||||
DMA_CH8 = DMAREQ_SPI0_RX,
|
||||
DMAREQ_SPI0_TX, /*!< SPI0 transmit DMA channel */
|
||||
DMA_CH9 = DMAREQ_SPI0_TX,
|
||||
DMAREQ_SPI1_RX, /*!< SPI1 receive DMA channel */
|
||||
DMA_CH10 = DMAREQ_SPI1_RX,
|
||||
DMAREQ_SPI1_TX, /*!< SPI1 transmit DMA channel */
|
||||
DMA_CH11 = DMAREQ_SPI1_TX,
|
||||
DMAREQ_I2C0_SLAVE, /*!< I2C0 Slave DMA channel */
|
||||
DMA_CH12 = DMAREQ_I2C0_SLAVE,
|
||||
DMAREQ_I2C0_MASTER, /*!< I2C0 Master DMA channel */
|
||||
DMA_CH13 = DMAREQ_I2C0_MASTER,
|
||||
DMAREQ_I2C1_SLAVE, /*!< I2C1 Slave DMA channel */
|
||||
DMA_CH14 = DMAREQ_I2C1_SLAVE,
|
||||
DMAREQ_I2C1_MASTER, /*!< I2C1 Master DMA channel */
|
||||
DMA_CH15 = DMAREQ_I2C1_MASTER,
|
||||
DMAREQ_I2C2_SLAVE, /*!< I2C2 Slave DMA channel */
|
||||
DMA_CH16 = DMAREQ_I2C2_SLAVE,
|
||||
DMAREQ_I2C2_MASTER, /*!< I2C2 Master DMA channel */
|
||||
DMA_CH17 = DMAREQ_I2C2_MASTER,
|
||||
DMAREQ_I2C0_MONITOR, /*!< I2C0 Monitor DMA channel */
|
||||
DMA_CH18 = DMAREQ_I2C0_MONITOR,
|
||||
DMAREQ_I2C1_MONITOR, /*!< I2C1 Monitor DMA channel */
|
||||
DMA_CH19 = DMAREQ_I2C1_MONITOR,
|
||||
DMAREQ_I2C2_MONITOR, /*!< I2C2 Monitor DMA channel */
|
||||
DMA_CH20 = DMAREQ_I2C2_MONITOR,
|
||||
RESERVED_SPARE_DMA,
|
||||
DMA_CH21 = RESERVED_SPARE_DMA
|
||||
} DMA_CHID_T;
|
||||
|
||||
/* On LPC540XX, Max DMA channel is 22 */
|
||||
#define MAX_DMA_CHANNEL (DMA_CH21+1)
|
||||
|
||||
/**
|
||||
* @brief DMA Controller register block structure
|
||||
*/
|
||||
typedef struct { /*!< DMA Structure */
|
||||
__IO uint32_t CTRL; /*!< DMA control register */
|
||||
__I uint32_t INTSTAT; /*!< DMA Interrupt status register */
|
||||
__IO uint32_t SRAMBASE; /*!< DMA SRAM address of the channel configuration table */
|
||||
__I uint32_t RESERVED2[5];
|
||||
LPC_DMA_COMMON_T DMACOMMON[1]; /*!< DMA shared channel (common) registers */
|
||||
__I uint32_t RESERVED0[225];
|
||||
LPC_DMA_CHANNEL_T DMACH[MAX_DMA_CHANNEL]; /*!< DMA channel registers */
|
||||
} LPC_DMA_T;
|
||||
|
||||
/** @defgroup DMA_COMMON_540XX CHIP: LPC540XX DMA Controller driver common functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize DMA controller
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_Init(LPC_DMA_T *pDMA)
|
||||
{
|
||||
(void) pDMA;
|
||||
Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_DMA);
|
||||
// FIXME - PRESETCTRL reset needed? Currently not defined
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize DMA controller
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_DeInit(LPC_DMA_T *pDMA)
|
||||
{
|
||||
(void) pDMA;
|
||||
Chip_Clock_DisablePeriphClock(SYSCON_CLOCK_DMA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA controller
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_Enable(LPC_DMA_T *pDMA)
|
||||
{
|
||||
pDMA->CTRL = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable DMA controller
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_Disable(LPC_DMA_T *pDMA)
|
||||
{
|
||||
pDMA->CTRL = 0;
|
||||
}
|
||||
|
||||
/* DMA interrupt status bits (common) */
|
||||
#define DMA_INTSTAT_ACTIVEINT 0x2 /*!< Summarizes whether any enabled interrupts are pending */
|
||||
#define DMA_INTSTAT_ACTIVEERRINT 0x4 /*!< Summarizes whether any error interrupts are pending */
|
||||
|
||||
/**
|
||||
* @brief Get pending interrupt or error interrupts
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return An Or'ed value of DMA_INTSTAT_* types
|
||||
* @note If any DMA channels have an active interrupt or error interrupt
|
||||
* pending, this functional will a common status that applies to all
|
||||
* channels.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetIntStatus(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->INTSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set DMA controller SRAM base address
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param base : The base address where the DMA descriptors will be stored
|
||||
* @return Nothing
|
||||
* @note A 256 byte block of memory aligned on a 256 byte boundary must be
|
||||
* provided for this function. It sets the base address used for
|
||||
* DMA descriptor table (16 descriptors total that use 16 bytes each).<br>
|
||||
*
|
||||
* A pre-defined table with correct alignment can be used for this
|
||||
* function by calling Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetSRAMBase(LPC_DMA_T *pDMA, uint32_t base)
|
||||
{
|
||||
pDMA->SRAMBASE = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns DMA controller SRAM base address
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return The base address where the DMA descriptors are stored
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetSRAMBase(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->SRAMBASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DMA_COMMON_540XX CHIP: LPC540XX DMA Controller driver common channel functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables a single DMA channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_EnableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].ENABLESET = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables a single DMA channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_DisableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].ENABLECLR = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all enabled DMA channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return An Or'ed value of all enabled DMA channels (0 - 15)
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) is enabled. A low state is disabled.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetEnabledChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].ENABLESET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all active DMA channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return An Or'ed value of all active DMA channels (0 - 15)
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) is active. A low state is inactive. A active
|
||||
* channel indicates that a DMA operation has been started but
|
||||
* not yet fully completed.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetActiveChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all busy DMA channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return An Or'ed value of all busy DMA channels (0 - 15)
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) is busy. A low state is not busy. A DMA
|
||||
* channel is considered busy when there is any operation
|
||||
* related to that channel in the DMA controller<65>s internal
|
||||
* pipeline.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetBusyChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].BUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns pending error interrupt status for all DMA channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return An Or'ed value of all channels (0 - 15) error interrupt status
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) has a pending error interrupt. A low state
|
||||
* indicates no error interrupt.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetErrorIntChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].ERRINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears a pending error interrupt status for a single DMA channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_ClearErrorIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].ERRINT = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a single DMA channel's interrupt used in common DMA interrupt
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_EnableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].INTENSET = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables a single DMA channel's interrupt used in common DMA interrupt
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_DisableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].INTENCLR = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns all enabled interrupt channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) has an enabled interrupt for the channel.
|
||||
* A low state indicates that the DMA channel will not contribute
|
||||
* to the common DMA interrupt status.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetEnableIntChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].INTENSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns active A interrupt status for all channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) has an active A interrupt for the channel.
|
||||
* A low state indicates that the A interrupt is not active.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetActiveIntAChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].INTA;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears active A interrupt status for a single channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_ClearActiveIntAChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].INTA = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns active B interrupt status for all channels
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @return Nothing
|
||||
* @note A high values in bits 0 .. 15 in the return values indicates
|
||||
* that the channel for that bit (bit 0 = channel 0, bit 1 -
|
||||
* channel 1, etc.) has an active B interrupt for the channel.
|
||||
* A low state indicates that the B interrupt is not active.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetActiveIntBChannels(LPC_DMA_T *pDMA)
|
||||
{
|
||||
return pDMA->DMACOMMON[0].INTB;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears active B interrupt status for a single channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_ClearActiveIntBChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].INTB = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the VALIDPENDING control bit for a single channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
* @note See the User Manual for more information for what this bit does.
|
||||
*
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetValidChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].SETVALID = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the TRIG bit for a single channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
* @note See the User Manual for more information for what this bit does.
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetTrigChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].SETTRIG = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aborts a DMA operation for a single channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
* @note To abort a channel, the channel should first be disabled. Then wait
|
||||
* until the channel is no longer busy by checking the corresponding
|
||||
* bit in BUSY. Finally, abort the channel operation. This prevents the
|
||||
* channel from restarting an incomplete operation when it is enabled
|
||||
* again.
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_AbortChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
pDMA->DMACOMMON[0].ABORT = (1 << ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DMA_CHANNEL_540XX CHIP: LPC540XX DMA Controller driver channel specific functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* DMA channel source/address/next descriptor */
|
||||
typedef struct {
|
||||
uint32_t xfercfg; /*!< Transfer configuration (only used in linked lists and ping-pong configs) */
|
||||
uint32_t source; /*!< DMA transfer source end address */
|
||||
uint32_t dest; /*!< DMA transfer desintation end address */
|
||||
uint32_t next; /*!< Link to next DMA descriptor, must be 16 byte aligned */
|
||||
} DMA_CHDESC_T;
|
||||
|
||||
/* Support macro for DMA_CHDESC_T */
|
||||
#define DMA_ADDR(addr) ((uint32_t) (addr))
|
||||
|
||||
/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase()
|
||||
function if a DMA SRAM table is needed. */
|
||||
extern DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
|
||||
|
||||
/* Support definitions for setting the configuration of a DMA channel. You
|
||||
will need to get more information on these options from the User manual. */
|
||||
#define DMA_CFG_PERIPHREQEN (1 << 0) /*!< Enables Peripheral DMA requests */
|
||||
#define DMA_CFG_HWTRIGEN (1 << 1) /*!< Use hardware triggering via imput mux */
|
||||
#define DMA_CFG_TRIGPOL_LOW (0 << 4) /*!< Hardware trigger is active low or falling edge */
|
||||
#define DMA_CFG_TRIGPOL_HIGH (1 << 4) /*!< Hardware trigger is active high or rising edge */
|
||||
#define DMA_CFG_TRIGTYPE_EDGE (0 << 5) /*!< Hardware trigger is edge triggered */
|
||||
#define DMA_CFG_TRIGTYPE_LEVEL (1 << 5) /*!< Hardware trigger is level triggered */
|
||||
#define DMA_CFG_TRIGBURST_SNGL (0 << 6) /*!< Single transfer. Hardware trigger causes a single transfer */
|
||||
#define DMA_CFG_TRIGBURST_BURST (1 << 6) /*!< Burst transfer (see UM) */
|
||||
#define DMA_CFG_BURSTPOWER_1 (0 << 8) /*!< Set DMA burst size to 1 transfer */
|
||||
#define DMA_CFG_BURSTPOWER_2 (1 << 8) /*!< Set DMA burst size to 2 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_4 (2 << 8) /*!< Set DMA burst size to 4 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_8 (3 << 8) /*!< Set DMA burst size to 8 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_16 (4 << 8) /*!< Set DMA burst size to 16 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_32 (5 << 8) /*!< Set DMA burst size to 32 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_64 (6 << 8) /*!< Set DMA burst size to 64 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_128 (7 << 8) /*!< Set DMA burst size to 128 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_256 (8 << 8) /*!< Set DMA burst size to 256 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_512 (9 << 8) /*!< Set DMA burst size to 512 transfers */
|
||||
#define DMA_CFG_BURSTPOWER_1024 (10 << 8) /*!< Set DMA burst size to 1024 transfers */
|
||||
#define DMA_CFG_BURSTPOWER(n) ((n) << 8) /*!< Set DMA burst size to 2^n transfers, max n=10 */
|
||||
#define DMA_CFG_SRCBURSTWRAP (1 << 14) /*!< Source burst wrapping is enabled for this DMA channel */
|
||||
#define DMA_CFG_DSTBURSTWRAP (1 << 15) /*!< Destination burst wrapping is enabled for this DMA channel */
|
||||
#define DMA_CFG_CHPRIORITY(p) ((p) << 16) /*!< Sets DMA channel priority, min 0 (highest), max 3 (lowest) */
|
||||
|
||||
/**
|
||||
* @brief Setup a DMA channel configuration
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param cfg : An Or'ed value of DMA_CFG_* values that define the channel's configuration
|
||||
* @return Nothing
|
||||
* @note This function sets up all configurable options for the DMA channel.
|
||||
* These options are usually set once for a channel and then unchanged.<br>
|
||||
*
|
||||
* The following example show how to configure the channel for peripheral
|
||||
* DMA requests, burst transfer size of 1 (in 'transfers', not bytes),
|
||||
* continuous reading of the same source address, incrementing destination
|
||||
* address, and highest channel priority.<br>
|
||||
* Example: Chip_DMA_SetupChannelConfig(pDMA, SSP0_RX_DMA,
|
||||
* (DMA_CFG_PERIPHREQEN | DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_1 |
|
||||
* DMA_CFG_SRCBURSTWRAP | DMA_CFG_CHPRIORITY(0)));<br>
|
||||
*
|
||||
* The following example show how to configure the channel for an external
|
||||
* trigger from the imput mux with low edge polarity, a burst transfer size of 8,
|
||||
* incrementing source and destination addresses, and lowest channel
|
||||
* priority.<br>
|
||||
* Example: Chip_DMA_SetupChannelConfig(pDMA, DMA_CH14,
|
||||
* (DMA_CFG_HWTRIGEN | DMA_CFG_TRIGPOL_LOW | DMA_CFG_TRIGTYPE_EDGE |
|
||||
* DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_8 |
|
||||
* DMA_CFG_CHPRIORITY(3)));<br>
|
||||
*
|
||||
* For non-peripheral DMA triggering (DMA_CFG_HWTRIGEN definition), use the
|
||||
* DMA input mux functions to configure the DMA trigger source for a DMA channel.
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetupChannelConfig(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg)
|
||||
{
|
||||
pDMA->DMACH[ch].CFG = cfg;
|
||||
}
|
||||
|
||||
/* DMA channel control and status register definitions */
|
||||
#define DMA_CTLSTAT_VALIDPENDING (1 << 0) /*!< Valid pending flag for this channel */
|
||||
#define DMA_CTLSTAT_TRIG (1 << 2) /*!< Trigger flag. Indicates that the trigger for this channel is currently set */
|
||||
|
||||
/**
|
||||
* @brief Returns channel specific status flags
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return AN Or'ed value of DMA_CTLSTAT_VALIDPENDING and DMA_CTLSTAT_TRIG
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_DMA_GetChannelStatus(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
return pDMA->DMACH[ch].XFERCFG;
|
||||
}
|
||||
|
||||
/* DMA channel transfer configuration registers definitions */
|
||||
#define DMA_XFERCFG_CFGVALID (1 << 0) /*!< Configuration Valid flag */
|
||||
#define DMA_XFERCFG_RELOAD (1 << 1) /*!< Indicates whether the channels control structure will be reloaded when the current descriptor is exhausted */
|
||||
#define DMA_XFERCFG_SWTRIG (1 << 2) /*!< Software Trigger */
|
||||
#define DMA_XFERCFG_CLRTRIG (1 << 3) /*!< Clear Trigger */
|
||||
#define DMA_XFERCFG_SETINTA (1 << 4) /*!< Set Interrupt flag A for this channel to fire when descriptor is complete */
|
||||
#define DMA_XFERCFG_SETINTB (1 << 5) /*!< Set Interrupt flag B for this channel to fire when descriptor is complete */
|
||||
#define DMA_XFERCFG_WIDTH_8 (0 << 8) /*!< 8-bit transfers are performed */
|
||||
#define DMA_XFERCFG_WIDTH_16 (1 << 8) /*!< 16-bit transfers are performed */
|
||||
#define DMA_XFERCFG_WIDTH_32 (2 << 8) /*!< 32-bit transfers are performed */
|
||||
#define DMA_XFERCFG_SRCINC_0 (0 << 12) /*!< DMA source address is not incremented after a transfer */
|
||||
#define DMA_XFERCFG_SRCINC_1 (1 << 12) /*!< DMA source address is incremented by 1 (width) after a transfer */
|
||||
#define DMA_XFERCFG_SRCINC_2 (2 << 12) /*!< DMA source address is incremented by 2 (width) after a transfer */
|
||||
#define DMA_XFERCFG_SRCINC_4 (3 << 12) /*!< DMA source address is incremented by 4 (width) after a transfer */
|
||||
#define DMA_XFERCFG_DSTINC_0 (0 << 14) /*!< DMA destination address is not incremented after a transfer */
|
||||
#define DMA_XFERCFG_DSTINC_1 (1 << 14) /*!< DMA destination address is incremented by 1 (width) after a transfer */
|
||||
#define DMA_XFERCFG_DSTINC_2 (2 << 14) /*!< DMA destination address is incremented by 2 (width) after a transfer */
|
||||
#define DMA_XFERCFG_DSTINC_4 (3 << 14) /*!< DMA destination address is incremented by 4 (width) after a transfer */
|
||||
#define DMA_XFERCFG_XFERCOUNT(n) ((n - 1) << 16) /*!< DMA transfer count in 'transfers', between (0)1 and (1023)1024 */
|
||||
|
||||
typedef enum {
|
||||
WIDTH_8_BITS = 0,
|
||||
WIDTH_16_BITS = 1,
|
||||
WIDTH_32_BITS = 2
|
||||
} DataWidth;
|
||||
|
||||
/**
|
||||
* @brief Setup a DMA channel transfer configuration
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param cfg : An Or'ed value of DMA_XFERCFG_* values that define the channel's transfer configuration
|
||||
* @return Nothing
|
||||
* @note This function sets up the transfer configuration for the DMA channel.<br>
|
||||
*
|
||||
* The following example show how to configure the channel's transfer for
|
||||
* multiple transfer descriptors (ie, ping-pong), interrupt 'A' trigger on
|
||||
* transfer descriptor completion, 128 byte size transfers, and source and
|
||||
* destination address increment.<br>
|
||||
* Example: Chip_DMA_SetupChannelTransfer(pDMA, SSP0_RX_DMA,
|
||||
* (DMA_XFERCFG_CFGVALID | DMA_XFERCFG_RELOAD | DMA_XFERCFG_SETINTA |
|
||||
* DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_SRCINC_1 | DMA_XFERCFG_DSTINC_1 |
|
||||
* DMA_XFERCFG_XFERCOUNT(128)));<br>
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetupChannelTransfer(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg)
|
||||
{
|
||||
pDMA->DMACH[ch].XFERCFG = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set DMA transfer register interrupt bits (safe)
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param mask : Bits to set
|
||||
* @return Nothing
|
||||
* @note This function safely sets bits in the DMA channel specific XFERCFG
|
||||
* register.
|
||||
*/
|
||||
void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Clear DMA transfer register interrupt bits (safe)
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param mask : Bits to clear
|
||||
* @return Nothing
|
||||
* @note This function safely clears bits in the DMA channel specific XFERCFG
|
||||
* register.
|
||||
*/
|
||||
void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Update the transfer size in an existing DMA channel transfer configuration
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param trans : Number of transfers to update the transfer configuration to (1 - 1023)
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans);
|
||||
|
||||
/**
|
||||
* @brief Sets a DMA channel configuration as valid
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetChannelValid(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a DMA channel configuration as invalid
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SetChannelInValid(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
Chip_DMA_ClearTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a software trigger of the DMA channel
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_DMA_SWTriggerChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
|
||||
{
|
||||
Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_SWTRIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets up a DMA channel with the passed DMA transfer descriptor
|
||||
* @param pDMA : The base of DMA controller on the chip
|
||||
* @param ch : DMA channel ID
|
||||
* @param desc : Pointer to DMA transfer descriptor
|
||||
* @return false if the DMA channel was active, otherwise true
|
||||
* @note This function will set the DMA descriptor in the SRAM table to the
|
||||
* the passed descriptor. This function is only meant to be used when
|
||||
* the DMA channel is not active and can be used to setup the
|
||||
* initial transfer for a linked list or ping-pong buffer or just a
|
||||
* single transfer without a next descriptor.<br>
|
||||
*
|
||||
* If using this function to write the initial transfer descriptor in
|
||||
* a linked list or ping-pong buffer configuration, it should contain a
|
||||
* non-NULL 'next' field pointer.
|
||||
*/
|
||||
bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc);
|
||||
|
||||
|
||||
void Chip_DMA_InitChannel( DMA_CHID_T channel, uint32_t src_address, uint32_t src_increment,
|
||||
uint32_t dst_address, uint32_t dst_increment, uint32_t xfr_width, uint32_t length_bytes, uint32_t priority);
|
||||
|
||||
void Chip_DMA_StartTransfer(DMA_CHID_T channel, uint32_t src_increment, uint32_t dst_increment, uint32_t xfr_width, uint32_t length_bytes);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DMA_540XX_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* @brief LPC540xx GPIO group driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C slave driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
#define NUMI2CDEVS 3
|
||||
|
||||
/* Clock and reset indexes */
|
||||
static const uint8_t resetIdx[NUMI2CDEVS] = {
|
||||
(uint8_t) RESET_I2C0, (uint8_t) RESET_I2C1,
|
||||
(uint8_t) RESET_I2C2
|
||||
};
|
||||
static const uint8_t ClockIdx[NUMI2CDEVS] = {
|
||||
(uint8_t) SYSCON_CLOCK_I2C0, (uint8_t) SYSCON_CLOCK_I2C1,
|
||||
(uint8_t) SYSCON_CLOCK_I2C2
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Returns the index needed for clock and reset lookup */
|
||||
static int returnClkIdx(LPC_I2C_T *pI2C)
|
||||
{
|
||||
if (pI2C == LPC_I2C1) {
|
||||
return 1;
|
||||
}
|
||||
else if (pI2C == LPC_I2C2) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Initializes the LPC_I2C peripheral */
|
||||
void Chip_I2C_Init(LPC_I2C_T *pI2C)
|
||||
{
|
||||
int clkIndex = returnClkIdx(pI2C);
|
||||
|
||||
/* Enable clock to I2C peripheral and reset */
|
||||
Chip_Clock_EnablePeriphClock((CHIP_SYSCON_CLOCK_T) ClockIdx[clkIndex]);
|
||||
Chip_SYSCON_PeriphReset((CHIP_SYSCON_PERIPH_RESET_T) resetIdx[clkIndex]);
|
||||
}
|
||||
|
||||
/* Shuts down the I2C controller block */
|
||||
void Chip_I2C_DeInit(LPC_I2C_T *pI2C)
|
||||
{
|
||||
int clkIndex = returnClkIdx(pI2C);
|
||||
|
||||
/* Disable clock to I2C peripheral */
|
||||
Chip_Clock_DisablePeriphClock((CHIP_SYSCON_CLOCK_T) ClockIdx[clkIndex]);
|
||||
}
|
||||
|
||||
/* Sets register bit values with mask */
|
||||
void Chip_I2C_SetRegMask(volatile uint32_t *pReg32, uint32_t mask, uint32_t bits)
|
||||
{
|
||||
*pReg32 = (*pReg32 & mask) | bits;
|
||||
}
|
||||
|
||||
/* Clears register bit values with mask */
|
||||
void Chip_I2C_ClearRegMask(volatile uint32_t *pReg32, uint32_t mask, uint32_t bits)
|
||||
{
|
||||
*pReg32 = (*pReg32 & mask) & ~bits;
|
||||
}
|
||||
|
||||
/* Sets I2C Clock Divider registers */
|
||||
void Chip_I2C_SetClockDiv(LPC_I2C_T *pI2C, uint32_t clkdiv)
|
||||
{
|
||||
if ((clkdiv >= 1) && (clkdiv <= 65536)) {
|
||||
pI2C->CLKDIV = clkdiv - 1;
|
||||
}
|
||||
else {
|
||||
pI2C->CLKDIV = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __I2C_COMMON_540XX_H_
|
||||
#define __I2C_COMMON_540XX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup I2C_540XX CHIP: LPC540xx I2C driver
|
||||
* @ingroup CHIP_540XX_Drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief I2C register block structure
|
||||
*/
|
||||
typedef struct { /* I2C0 Structure */
|
||||
__IO uint32_t CFG; /*!< I2C Configuration Register common for Master, Slave and Monitor */
|
||||
__IO uint32_t STAT; /*!< I2C Status Register common for Master, Slave and Monitor */
|
||||
__IO uint32_t INTENSET; /*!< I2C Interrupt Enable Set Register common for Master, Slave and Monitor */
|
||||
__O uint32_t INTENCLR; /*!< I2C Interrupt Enable Clear Register common for Master, Slave and Monitor */
|
||||
__IO uint32_t TIMEOUT; /*!< I2C Timeout value Register */
|
||||
__IO uint32_t CLKDIV; /*!< I2C Clock Divider Register */
|
||||
__I uint32_t INTSTAT; /*!< I2C Interrupt Status Register */
|
||||
__I uint32_t RESERVED0;
|
||||
__IO uint32_t MSTCTL; /*!< I2C Master Control Register */
|
||||
__IO uint32_t MSTTIME; /*!< I2C Master Time Register for SCL */
|
||||
__IO uint32_t MSTDAT; /*!< I2C Master Data Register */
|
||||
__I uint32_t RESERVED1[5];
|
||||
__IO uint32_t SLVCTL; /*!< I2C Slave Control Register */
|
||||
__IO uint32_t SLVDAT; /*!< I2C Slave Data Register */
|
||||
__IO uint32_t SLVADR[4]; /*!< I2C Slave Address Registers */
|
||||
__IO uint32_t SLVQUAL0; /*!< I2C Slave Address Qualifier 0 Register */
|
||||
__I uint32_t RESERVED2[9];
|
||||
__I uint32_t MONRXDAT; /*!< I2C Monitor Data Register */
|
||||
} LPC_I2C_T;
|
||||
|
||||
/*
|
||||
* @brief I2C Configuration register Bit definition
|
||||
*/
|
||||
#define I2C_CFG_MSTEN (1 << 0) /*!< Master Enable/Disable Bit */
|
||||
#define I2C_CFG_SLVEN (1 << 1) /*!< Slave Enable/Disable Bit */
|
||||
#define I2C_CFG_MONEN (1 << 2) /*!< Monitor Enable/Disable Bit */
|
||||
#define I2C_CFG_TIMEOUTEN (1 << 3) /*!< Timeout Enable/Disable Bit */
|
||||
#define I2C_CFG_MONCLKSTR (1 << 4) /*!< Monitor Clock Stretching Bit */
|
||||
#define I2C_CFG_MASK ((uint32_t) 0x1F) /*!< Configuration Register Mask */
|
||||
|
||||
/*
|
||||
* @brief I2C Status register Bit definition
|
||||
*/
|
||||
#define I2C_STAT_MSTPENDING (1 << 0) /*!< Master Pending Status Bit */
|
||||
#define I2C_STAT_MSTSTATE (0x7 << 1) /*!< Master State Code */
|
||||
#define I2C_STAT_MSTRARBLOSS (1 << 4) /*!< Master Arbitration Loss Bit */
|
||||
#define I2C_STAT_MSTSTSTPERR (1 << 6) /*!< Master Start Stop Error Bit */
|
||||
#define I2C_STAT_SLVPENDING (1 << 8) /*!< Slave Pending Status Bit */
|
||||
#define I2C_STAT_SLVSTATE (0x3 << 9) /*!< Slave State Code */
|
||||
#define I2C_STAT_SLVNOTSTR (1 << 11) /*!< Slave not stretching Clock Bit */
|
||||
#define I2C_STAT_SLVIDX (0x3 << 12) /*!< Slave Address Index */
|
||||
#define I2C_STAT_SLVSEL (1 << 14) /*!< Slave Selected Bit */
|
||||
#define I2C_STAT_SLVDESEL (1 << 15) /*!< Slave Deselect Bit */
|
||||
#define I2C_STAT_MONRDY (1 << 16) /*!< Monitor Ready Bit */
|
||||
#define I2C_STAT_MONOV (1 << 17) /*!< Monitor Overflow Flag */
|
||||
#define I2C_STAT_MONACTIVE (1 << 18) /*!< Monitor Active Flag */
|
||||
#define I2C_STAT_MONIDLE (1 << 19) /*!< Monitor Idle Flag */
|
||||
#define I2C_STAT_EVENTTIMEOUT (1 << 24) /*!< Event Timeout Interrupt Flag */
|
||||
#define I2C_STAT_SCLTIMEOUT (1 << 25) /*!< SCL Timeout Interrupt Flag */
|
||||
|
||||
#define I2C_STAT_MSTCODE_IDLE (0) /*!< Master Idle State Code */
|
||||
#define I2C_STAT_MSTCODE_RXREADY (1) /*!< Master Receive Ready State Code */
|
||||
#define I2C_STAT_MSTCODE_TXREADY (2) /*!< Master Transmit Ready State Code */
|
||||
#define I2C_STAT_MSTCODE_NACKADR (3) /*!< Master NACK by slave on address State Code */
|
||||
#define I2C_STAT_MSTCODE_NACKDAT (4) /*!< Master NACK by slave on data State Code */
|
||||
|
||||
#define I2C_STAT_SLVCODE_ADDR (0) /*!< Master Idle State Code */
|
||||
#define I2C_STAT_SLVCODE_RX (1) /*!< Received data is available Code */
|
||||
#define I2C_STAT_SLVCODE_TX (2) /*!< Data can be transmitted Code */
|
||||
|
||||
/*
|
||||
* @brief I2C Interrupt Enable Set register Bit definition
|
||||
*/
|
||||
#define I2C_INTENSET_MSTPENDING (1 << 0) /*!< Master Pending Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_MSTRARBLOSS (1 << 4) /*!< Master Arbitration Loss Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_MSTSTSTPERR (1 << 6) /*!< Master Start Stop Error Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_SLVPENDING (1 << 8) /*!< Slave Pending Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_SLVNOTSTR (1 << 11) /*!< Slave not stretching Clock Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_SLVDESEL (1 << 15) /*!< Slave Deselect Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_MONRDY (1 << 16) /*!< Monitor Ready Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_MONOV (1 << 17) /*!< Monitor Overflow Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_MONIDLE (1 << 19) /*!< Monitor Idle Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_EVENTTIMEOUT (1 << 24) /*!< Event Timeout Interrupt Enable Bit */
|
||||
#define I2C_INTENSET_SCLTIMEOUT (1 << 25) /*!< SCL Timeout Interrupt Enable Bit */
|
||||
|
||||
/*
|
||||
* @brief I2C Interrupt Enable Clear register Bit definition
|
||||
*/
|
||||
#define I2C_INTENCLR_MSTPENDING (1 << 0) /*!< Master Pending Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_MSTRARBLOSS (1 << 4) /*!< Master Arbitration Loss Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_MSTSTSTPERR (1 << 6) /*!< Master Start Stop Error Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_SLVPENDING (1 << 8) /*!< Slave Pending Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_SLVNOTSTR (1 << 11) /*!< Slave not stretching Clock Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_SLVDESEL (1 << 15) /*!< Slave Deselect Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_MONRDY (1 << 16) /*!< Monitor Ready Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_MONOV (1 << 17) /*!< Monitor Overflow Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_MONIDLE (1 << 19) /*!< Monitor Idle Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_EVENTTIMEOUT (1 << 24) /*!< Event Timeout Interrupt Clear Bit */
|
||||
#define I2C_INTENCLR_SCLTIMEOUT (1 << 25) /*!< SCL Timeout Interrupt Clear Bit */
|
||||
|
||||
/*
|
||||
* @brief I2C TimeOut Value Macro
|
||||
*/
|
||||
#define I2C_TIMEOUT_VAL(n) (((uint32_t) ((n) - 1) & 0xFFF0) | 0x000F) /*!< Macro for Timeout value register */
|
||||
|
||||
/*
|
||||
* @brief I2C Interrupt Status register Bit definition
|
||||
*/
|
||||
#define I2C_INTSTAT_MSTPENDING (1 << 0) /*!< Master Pending Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_MSTRARBLOSS (1 << 4) /*!< Master Arbitration Loss Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_MSTSTSTPERR (1 << 6) /*!< Master Start Stop Error Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_SLVPENDING (1 << 8) /*!< Slave Pending Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_SLVNOTSTR (1 << 11) /*!< Slave not stretching Clock Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_SLVDESEL (1 << 15) /*!< Slave Deselect Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_MONRDY (1 << 16) /*!< Monitor Ready Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_MONOV (1 << 17) /*!< Monitor Overflow Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_MONIDLE (1 << 19) /*!< Monitor Idle Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_EVENTTIMEOUT (1 << 24) /*!< Event Timeout Interrupt Status Bit */
|
||||
#define I2C_INTSTAT_SCLTIMEOUT (1 << 25) /*!< SCL Timeout Interrupt Status Bit */
|
||||
|
||||
/*
|
||||
* @brief I2C Master Control register Bit definition
|
||||
*/
|
||||
#define I2C_MSTCTL_MSTCONTINUE (1 << 0) /*!< Master Continue Bit */
|
||||
#define I2C_MSTCTL_MSTSTART (1 << 1) /*!< Master Start Control Bit */
|
||||
#define I2C_MSTCTL_MSTSTOP (1 << 2) /*!< Master Stop Control Bit */
|
||||
#define I2C_MSTCTL_MSTDMA (1 << 3) /*!< Master DMA Enable Bit */
|
||||
|
||||
/*
|
||||
* @brief I2C Master Time Register Field definition
|
||||
*/
|
||||
#define I2C_MSTTIME_MSTSCLLOW (0x07 << 0) /*!< Master SCL Low Time field */
|
||||
#define I2C_MSTTIME_MSTSCLHIGH (0x07 << 4) /*!< Master SCL High Time field */
|
||||
|
||||
/*
|
||||
* @brief I2C Master Data Mask
|
||||
*/
|
||||
#define I2C_MSTDAT_DATAMASK ((uint32_t) 0x00FF << 0) /*!< Master data mask */
|
||||
|
||||
/*
|
||||
* @brief I2C Slave Control register Bit definition
|
||||
*/
|
||||
#define I2C_SLVCTL_SLVCONTINUE (1 << 0) /*!< Slave Continue Bit */
|
||||
#define I2C_SLVCTL_SLVNACK (1 << 1) /*!< Slave NACK Bit */
|
||||
#define I2C_SLVCTL_SLVDMA (1 << 3) /*!< Slave DMA Enable Bit */
|
||||
|
||||
/*
|
||||
* @brief I2C Slave Data Mask
|
||||
*/
|
||||
#define I2C_SLVDAT_DATAMASK ((uint32_t) 0x00FF << 0) /*!< Slave data mask */
|
||||
|
||||
/*
|
||||
* @brief I2C Slave Address register Bit definition
|
||||
*/
|
||||
#define I2C_SLVADR_SADISABLE (1 << 0) /*!< Slave Address n Disable Bit */
|
||||
#define I2C_SLVADR_SLVADR (0x7F << 1) /*!< Slave Address field */
|
||||
#define I2C_SLVADR_MASK ((uint32_t) 0x00FF) /*!< Slave Address Mask */
|
||||
|
||||
/*
|
||||
* @brief I2C Slave Address Qualifier 0 Register Bit definition
|
||||
*/
|
||||
#define I2C_SLVQUAL_QUALMODE0 (1 << 0) /*!< Slave Qualifier Mode Enable Bit */
|
||||
#define I2C_SLVQUAL_SLVQUAL0 (0x7F << 1) /*!< Slave Qualifier Address for Address 0 */
|
||||
|
||||
/*
|
||||
* @brief I2C Monitor Data Register Bit definition
|
||||
*/
|
||||
#define I2C_MONRXDAT_DATA (0xFF << 0) /*!< Monitor Function Receive Data Field */
|
||||
#define I2C_MONRXDAT_MONSTART (1 << 8) /*!< Monitor Received Start Bit */
|
||||
#define I2C_MONRXDAT_MONRESTART (1 << 9) /*!< Monitor Received Repeated Start Bit */
|
||||
#define I2C_MONRXDAT_MONNACK (1 << 10) /*!< Monitor Received Nack Bit */
|
||||
|
||||
/**
|
||||
* @brief Initialize I2C Interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function enables the I2C clock for both the master and
|
||||
* slave interfaces if the I2C channel.
|
||||
|
||||
*/
|
||||
void Chip_I2C_Init(LPC_I2C_T *pI2C);
|
||||
|
||||
/**
|
||||
* @brief Shutdown I2C Interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function disables the I2C clock for both the master and
|
||||
* slave interfaces if the I2C channel.
|
||||
*/
|
||||
void Chip_I2C_DeInit(LPC_I2C_T *pI2C);
|
||||
|
||||
/**
|
||||
* @brief Sets register bit values with mask
|
||||
* @param pReg32 : Pointer to 32-bit register to set bits for
|
||||
* @param mask : Zero write mask, will mask these bits are write back as 0
|
||||
* @param bits : Bits to set
|
||||
* @return Nothing
|
||||
* @note This function is needed for read-modify-write operations where the register
|
||||
* being changed has read bits that are undefined, but must be written back as 0.
|
||||
*/
|
||||
void Chip_I2C_SetRegMask(volatile uint32_t *pReg32, uint32_t mask, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Clears register bit values with mask
|
||||
* @param pReg32 : Pointer to 32-bit register to clear bits for
|
||||
* @param mask : Zero write mask, will mask these bits are write back as 0
|
||||
* @param bits : Bits to clear
|
||||
* @return Nothing
|
||||
* @note This function is needed for read-modify-write operations where the register
|
||||
* being changed has read bits that are undefined, but must be written back as 0.
|
||||
*/
|
||||
void Chip_I2C_ClearRegMask(volatile uint32_t *pReg32, uint32_t mask, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Sets I2C Clock Divider registers
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param clkdiv : Clock Divider value for I2C, value is between (1 - 65536)
|
||||
* @return Nothing
|
||||
* @note The clock to I2C block is determined by the following formula (I2C_PCLK
|
||||
* is the frequency of the system clock): <br>
|
||||
* I2C Clock Frequency = (I2C_PCLK)/clkdiv;<br>
|
||||
* This divider must be setup for both the master and slave modes of the
|
||||
* controller. When used in master mode, this divider is used with the MSTTIME
|
||||
* register to generate the master I2C clock. Since the MSTTIME register has a
|
||||
* limited range of divide values, this value should be selected to give an I2C
|
||||
* clock rate that is about 2x to 18x greater than the desired master clock rate.
|
||||
*/
|
||||
void Chip_I2C_SetClockDiv(LPC_I2C_T *pI2C, uint32_t clkdiv);
|
||||
|
||||
/**
|
||||
* @brief Get I2C Clock Divider registers
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Clock Divider value
|
||||
* @note Return the divider value for the I2C block
|
||||
* It is the CLKDIV register value + 1
|
||||
*/
|
||||
static INLINE uint32_t Chip_I2C_GetClockDiv(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->CLKDIV & 0xFFFF) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2C Interrupts
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param intEn : ORed Value of I2C_INTENSET_* values to enable
|
||||
* @return Nothing
|
||||
*/
|
||||
static INLINE void Chip_I2C_EnableInt(LPC_I2C_T *pI2C, uint32_t intEn)
|
||||
{
|
||||
pI2C->INTENSET = intEn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C Interrupts
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param intClr : ORed Value of I2C_INTENSET_* values to disable
|
||||
* @return Nothing
|
||||
*/
|
||||
static INLINE void Chip_I2C_DisableInt(LPC_I2C_T *pI2C, uint32_t intClr)
|
||||
{
|
||||
pI2C->INTENCLR = intClr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C Interrupts
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param intClr : ORed Value of I2C_INTENSET_* values to disable
|
||||
* @return Nothing
|
||||
* @note It is recommended to use the Chip_I2C_DisableInt() function
|
||||
* instead of this function.
|
||||
*/
|
||||
static INLINE void Chip_I2C_ClearInt(LPC_I2C_T *pI2C, uint32_t intClr)
|
||||
{
|
||||
Chip_I2C_DisableInt(pI2C, intClr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns pending I2C Interrupts
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return All pending interrupts, mask with I2C_INTENSET_* to determine specific interrupts
|
||||
*/
|
||||
static INLINE uint32_t Chip_I2C_GetPendingInt(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return pI2C->INTSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __I2C_COMMON_540XX_H_ */
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C master driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Sets HIGH and LOW duty cycle registers */
|
||||
void Chip_I2CM_SetDutyCycle(LPC_I2C_T *pI2C, uint16_t sclH, uint16_t sclL)
|
||||
{
|
||||
/* Limit to usable range of timing values */
|
||||
if (sclH < 2) {
|
||||
sclH = 2;
|
||||
}
|
||||
else if (sclH > 9) {
|
||||
sclH = 9;
|
||||
}
|
||||
if (sclL < 2) {
|
||||
sclL = 2;
|
||||
}
|
||||
else if (sclL > 9) {
|
||||
sclL = 9;
|
||||
}
|
||||
|
||||
pI2C->MSTTIME = (((sclH - 2) & 0x07) << 4) | ((sclL - 2) & 0x07);
|
||||
}
|
||||
|
||||
/* Set up bus speed for LPC_I2C interface */
|
||||
uint32_t Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed)
|
||||
{
|
||||
#if 0
|
||||
uint32_t scl;
|
||||
scl = Chip_Clock_GetAsyncSyscon_ClockRate() / (Chip_I2C_GetClockDiv(pI2C) * busSpeed);
|
||||
Chip_I2CM_SetDutyCycle(pI2C, (scl >> 1), (scl - (scl >> 1)));
|
||||
#endif
|
||||
|
||||
// Wecan ToDo modify base on lpconen_2_14_1 ==> hw_i2cmd.c => i2cm_set_clock_rate 2015.06.04
|
||||
uint32_t scl;
|
||||
uint32_t inRate,div;
|
||||
inRate = Chip_Clock_GetAsyncSyscon_ClockRate();
|
||||
|
||||
/* Determine the best I2C clock dividers to generate the target I2C master clock */
|
||||
/* The maximum SCL and SCH dividers are 7, for a maximum divider set of 14 */
|
||||
/* The I2C master divider is between 1 and 65536. */
|
||||
|
||||
/* Pick a main I2C divider that allows centered SCL/SCH dividers */
|
||||
div = inRate / (busSpeed << 3);
|
||||
if (div == 0) {
|
||||
div = 1;
|
||||
}
|
||||
Chip_I2C_SetClockDiv(pI2C, div);
|
||||
|
||||
/* Determine SCL/SCH dividers */
|
||||
scl = inRate / (div * busSpeed);
|
||||
Chip_I2CM_SetDutyCycle(pI2C, (scl >> 1), (scl - (scl >> 1)));
|
||||
|
||||
return inRate / (div * scl);
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
/* Master transfer state change handler handler */
|
||||
uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
|
||||
{
|
||||
uint32_t status = Chip_I2CM_GetStatus(pI2C);
|
||||
|
||||
if (status & I2C_STAT_MSTRARBLOSS) {
|
||||
/* Master Lost Arbitration */
|
||||
/* Set transfer status as Arbitration Lost */
|
||||
xfer->status = I2CM_STATUS_ARBLOST;
|
||||
/* Clear Status Flags */
|
||||
Chip_I2CM_ClearStatus(pI2C, I2C_STAT_MSTRARBLOSS);
|
||||
/* Master continue */
|
||||
if (status & I2C_STAT_MSTPENDING) {
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
}
|
||||
}
|
||||
else if (status & I2C_STAT_MSTSTSTPERR) {
|
||||
/* Master Start Stop Error */
|
||||
/* Set transfer status as Bus Error */
|
||||
xfer->status = I2CM_STATUS_BUS_ERROR;
|
||||
/* Clear Status Flags */
|
||||
Chip_I2CM_ClearStatus(pI2C, I2C_STAT_MSTSTSTPERR);
|
||||
|
||||
/* Master continue */
|
||||
if (status & I2C_STAT_MSTPENDING) {
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
}
|
||||
}
|
||||
else if (status & I2C_STAT_MSTPENDING) {
|
||||
/* Master is Pending */
|
||||
/* Branch based on Master State Code */
|
||||
switch (Chip_I2CM_GetMasterState(pI2C)) {
|
||||
case I2C_STAT_MSTCODE_IDLE: /* Master idle */
|
||||
/* Can transition to idle between transmit and receive states */
|
||||
if (xfer->txSz) {
|
||||
/* Start transmit state */
|
||||
Chip_I2CM_WriteByte(pI2C, (xfer->slaveAddr << 1));
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTART;
|
||||
}
|
||||
else if (xfer->rxSz) {
|
||||
/* Start receive state with start ot repeat start */
|
||||
Chip_I2CM_WriteByte(pI2C, (xfer->slaveAddr << 1) | 0x1);
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTART;
|
||||
}
|
||||
else {
|
||||
/* No data to send, done */
|
||||
xfer->status = I2CM_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_STAT_MSTCODE_RXREADY: /* Receive data is available */
|
||||
/* Read Data up until the buffer size */
|
||||
if (xfer->rxSz) {
|
||||
*xfer->rxBuff = pI2C->MSTDAT;
|
||||
xfer->rxBuff++;
|
||||
xfer->rxSz--;
|
||||
}
|
||||
|
||||
if (xfer->rxSz) {
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
}
|
||||
else {
|
||||
/* Last byte to receive, send stop after byte received */
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE | I2C_MSTCTL_MSTSTOP;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_STAT_MSTCODE_TXREADY: /* Master Transmit available */
|
||||
if (xfer->txSz) {
|
||||
/* If Tx data available transmit data and continue */
|
||||
pI2C->MSTDAT = (uint32_t) *xfer->txBuff;
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
xfer->txBuff++;
|
||||
xfer->txSz--;
|
||||
}
|
||||
else if (xfer->rxSz == 0) {
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTOP;
|
||||
}
|
||||
else {
|
||||
/* Start receive state with start ot repeat start */
|
||||
Chip_I2CM_WriteByte(pI2C, (xfer->slaveAddr << 1) | 0x1);
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTART;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_STAT_MSTCODE_NACKADR: /* Slave address was NACK'ed */
|
||||
/* Set transfer status as NACK on address */
|
||||
xfer->status = I2CM_STATUS_NAK_ADR;
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTOP;
|
||||
break;
|
||||
|
||||
case I2C_STAT_MSTCODE_NACKDAT: /* Slave data was NACK'ed */
|
||||
/* Set transfer status as NACK on data */
|
||||
xfer->status = I2CM_STATUS_NAK_DAT;
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Illegal I2C master state machine case. This should never happen.
|
||||
Try to advance state machine by continuing. */
|
||||
xfer->status = I2CM_STATUS_ERROR;
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Unsupported operation. This may be a call to the master handler
|
||||
for a wrong interrupt type. This handler should only be called when a
|
||||
master arbitration loss, master start/stop error, or master pending status
|
||||
occurs. */
|
||||
xfer->status = I2CM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return xfer->status != I2CM_STATUS_BUSY;
|
||||
}
|
||||
|
||||
/* Transmit and Receive data in master mode */
|
||||
void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
|
||||
{
|
||||
/* set the transfer status as busy */
|
||||
xfer->status = I2CM_STATUS_BUSY;
|
||||
|
||||
/* Reset master state machine */
|
||||
Chip_I2CM_Disable(pI2C);
|
||||
Chip_I2CM_Enable(pI2C);
|
||||
|
||||
/* Clear controller state. */
|
||||
Chip_I2CM_ClearStatus(pI2C, I2C_STAT_MSTRARBLOSS | I2C_STAT_MSTSTSTPERR);
|
||||
|
||||
/* Handle transfer via initial call to handler */
|
||||
Chip_I2CM_XferHandler(pI2C, xfer);
|
||||
}
|
||||
|
||||
/* Transmit and Receive data in master mode */
|
||||
uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
|
||||
{
|
||||
/* start transfer */
|
||||
Chip_I2CM_Xfer(pI2C, xfer);
|
||||
|
||||
while (xfer->status == I2CM_STATUS_BUSY) {
|
||||
/* wait for status change interrupt */
|
||||
while (!Chip_I2CM_IsMasterPending(pI2C)) {}
|
||||
/* call state change handler */
|
||||
Chip_I2CM_XferHandler(pI2C, xfer);
|
||||
}
|
||||
|
||||
return (xfer->status == I2CM_STATUS_OK);
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __I2CM_540XX_H_
|
||||
#define __I2CM_540XX_H_
|
||||
|
||||
#include "i2c_common_540xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup I2CM_540XX CHIP: LPC540xx I2C master-only driver
|
||||
* @ingroup I2C_540XX
|
||||
* This driver only works in master mode. To describe the I2C transactions
|
||||
* following symbols are used in driver documentation.
|
||||
*
|
||||
* Key to symbols
|
||||
* ==============
|
||||
* S (1 bit) : Start bit
|
||||
* P (1 bit) : Stop bit
|
||||
* Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
|
||||
* A, NA (1 bit) : Acknowledge and Not-Acknowledge bit.
|
||||
* Addr (7 bits): I2C 7 bit address. Note that this can be expanded as usual to
|
||||
* get a 10 bit I2C address.
|
||||
* Data (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh
|
||||
* for 16 bit data.
|
||||
* [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** I2CM_540XX_STATUS_TYPES I2C master transfer status types
|
||||
*/
|
||||
|
||||
#define I2CM_STATUS_OK 0x00 /*!< Requested Request was executed successfully. */
|
||||
#define I2CM_STATUS_ERROR 0x01 /*!< Unknown error condition. */
|
||||
#define I2CM_STATUS_NAK_ADR 0x02 /*!< No acknowledgement received from slave during address phase. */
|
||||
#define I2CM_STATUS_BUS_ERROR 0x03 /*!< I2C bus error */
|
||||
#define I2CM_STATUS_NAK_DAT 0x04 /*!< No acknowledgement received from slave during address phase. */
|
||||
#define I2CM_STATUS_ARBLOST 0x05 /*!< Arbitration lost. */
|
||||
#define I2CM_STATUS_BUSY 0xFF /*!< I2C transmistter is busy. */
|
||||
|
||||
/**
|
||||
* @brief Master transfer data structure definitions
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t *txBuff; /*!< Pointer to array of bytes to be transmitted */
|
||||
uint8_t *rxBuff; /*!< Pointer memory where bytes received from I2C be stored */
|
||||
volatile uint16_t txSz; /*!< Number of bytes in transmit array,
|
||||
if 0 only receive transfer will be carried on */
|
||||
volatile uint16_t rxSz; /*!< Number of bytes to received,
|
||||
if 0 only transmission we be carried on */
|
||||
volatile uint16_t status; /*!< Status of the current I2C transfer */
|
||||
uint8_t slaveAddr; /*!< 7-bit I2C Slave address */
|
||||
} I2CM_XFER_T;
|
||||
|
||||
/**
|
||||
* @brief Sets HIGH and LOW duty cycle registers
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param sclH : Number of I2C_PCLK cycles for the SCL HIGH time value between (2 - 9).
|
||||
* @param sclL : Number of I2C_PCLK cycles for the SCL LOW time value between (2 - 9).
|
||||
* @return Nothing
|
||||
* @note The I2C clock divider should be set to the appropriate value before calling this function
|
||||
* The I2C baud is determined by the following formula: <br>
|
||||
* I2C_bitFrequency = (I2C_PCLK)/(I2C_CLKDIV * (sclH + sclL)) <br>
|
||||
* where I2C_PCLK is the frequency of the System clock and I2C_CLKDIV is I2C clock divider
|
||||
*/
|
||||
void Chip_I2CM_SetDutyCycle(LPC_I2C_T *pI2C, uint16_t sclH, uint16_t sclL);
|
||||
|
||||
/**
|
||||
* @brief Set up bus speed for LPC_I2C controller
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param busSpeed : I2C bus clock rate
|
||||
* @return Nothing
|
||||
* @note Per I2C specification the busSpeed should be
|
||||
* @li 100000 for Standard mode
|
||||
* @li 400000 for Fast mode
|
||||
* @li 1000000 for Fast mode plus
|
||||
* IOCON registers corresponding to I2C pads should be updated
|
||||
* according to the bus mode.
|
||||
*/
|
||||
uint32_t Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed);
|
||||
|
||||
/**
|
||||
* @brief Enable I2C Master interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note
|
||||
*/
|
||||
static INLINE void Chip_I2CM_Enable(LPC_I2C_T *pI2C)
|
||||
{
|
||||
Chip_I2C_SetRegMask(&pI2C->CFG, I2C_CFG_MASK, I2C_CFG_MSTEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C Master interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note
|
||||
*/
|
||||
static INLINE void Chip_I2CM_Disable(LPC_I2C_T *pI2C)
|
||||
{
|
||||
Chip_I2C_ClearRegMask(&pI2C->CFG, I2C_CFG_MASK, I2C_CFG_MSTEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C Status
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return I2C Status register value
|
||||
* @note This function returns the value of the status register.
|
||||
*/
|
||||
static INLINE uint32_t Chip_I2CM_GetStatus(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return pI2C->STAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C status bits (master)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param clrStatus : Status bit to clear, ORed Value of I2C_STAT_MSTRARBLOSS and I2C_STAT_MSTSTSTPERR
|
||||
* @return Nothing
|
||||
* @note This function clears selected status flags.
|
||||
*/
|
||||
static INLINE void Chip_I2CM_ClearStatus(LPC_I2C_T *pI2C, uint32_t clrStatus)
|
||||
{
|
||||
/* Clear Master Arbitration Loss and Start, Stop Error */
|
||||
pI2C->STAT = clrStatus & (I2C_STAT_MSTRARBLOSS | I2C_STAT_MSTSTSTPERR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if I2C Master is pending
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Returns TRUE if the Master is pending else returns FALSE
|
||||
* @note
|
||||
*/
|
||||
static INLINE bool Chip_I2CM_IsMasterPending(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_MSTPENDING) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current state of the I2C Master
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Master State Code, a value in the range of 0 - 4
|
||||
* @note After the Master is pending this state code tells the reason
|
||||
* for Master pending.
|
||||
*/
|
||||
static INLINE uint32_t Chip_I2CM_GetMasterState(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_MSTSTATE) >> 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit START or Repeat-START signal on I2C bus
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function sets the controller to transmit START condition when
|
||||
* the bus becomes free. This should be called only when master is pending.
|
||||
* The function writes a complete value to Master Control register, ORing is not advised.
|
||||
*/
|
||||
static INLINE void Chip_I2CM_SendStart(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit STOP signal on I2C bus
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function sets the controller to transmit STOP condition.
|
||||
* This should be called only when master is pending. The function writes a
|
||||
* complete value to Master Control register, ORing is not advised.
|
||||
*/
|
||||
static INLINE void Chip_I2CM_SendStop(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTSTOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Master Continue transfer operation
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function sets the master controller to continue transmission.
|
||||
* This should be called only when master is pending. The function writes a
|
||||
* complete value to Master Control register, ORing is not advised.
|
||||
*/
|
||||
static INLINE void Chip_I2CM_MasterContinue(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->MSTCTL = I2C_MSTCTL_MSTCONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a single data byte through the I2C peripheral (master)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param data : Byte to transmit
|
||||
* @return Nothing
|
||||
* @note This function attempts to place a byte into the I2C Master
|
||||
* Data Register
|
||||
*
|
||||
*/
|
||||
static INLINE void Chip_I2CM_WriteByte(LPC_I2C_T *pI2C, uint8_t data)
|
||||
{
|
||||
pI2C->MSTDAT = (uint32_t) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a single byte data from the I2C peripheral (master)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return A single byte of data read
|
||||
* @note This function reads a byte from the I2C receive hold register
|
||||
* regardless of I2C state.
|
||||
*/
|
||||
static INLINE uint8_t Chip_I2CM_ReadByte(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (uint8_t) (pI2C->MSTDAT & I2C_MSTDAT_DATAMASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transfer state change handler
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param xfer : Pointer to a I2CM_XFER_T structure see notes below
|
||||
* @return Returns non-zero value on completion of transfer. The @a status
|
||||
* member of @a xfer structure contains the current status of the
|
||||
* transfer at the end of the call.
|
||||
* @note
|
||||
* The parameter @a xfer should be same as the one passed to Chip_I2CM_Xfer()
|
||||
* routine. This function should be called from the I2C interrupt handler
|
||||
* only when a master interrupt occurs.
|
||||
*/
|
||||
uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive data in master mode
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param xfer : Pointer to a I2CM_XFER_T structure see notes below
|
||||
* @return Nothing
|
||||
* @note
|
||||
* The parameter @a xfer should have its member @a slaveAddr initialized
|
||||
* to the 7-Bit slave address to which the master will do the xfer, Bit0
|
||||
* to bit6 should have the address and Bit8 is ignored. During the transfer
|
||||
* no code (like event handler) must change the content of the memory
|
||||
* pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be
|
||||
* initialized to the memory from which the I2C must pick the data to be
|
||||
* transfered to slave and the number of bytes to send respectively, similarly
|
||||
* @a rxBuff and @a rxSz must have pointer to memroy where data received
|
||||
* from slave be stored and the number of data to get from slave respectilvely.
|
||||
* Following types of transfers are possible:
|
||||
* - Write-only transfer: When @a rxSz member of @a xfer is set to 0.
|
||||
*
|
||||
* S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A] P
|
||||
*
|
||||
* - If I2CM_XFER_OPTION_IGNORE_NACK is set in @a options memeber
|
||||
*
|
||||
* S Addr Wr [A] txBuff0 [A or NA] ... txBuffN [A or NA] P
|
||||
*
|
||||
* - Read-only transfer: When @a txSz member of @a xfer is set to 0.
|
||||
*
|
||||
* S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P
|
||||
*
|
||||
* - If I2CM_XFER_OPTION_LAST_RX_ACK is set in @a options memeber
|
||||
*
|
||||
* S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] A P
|
||||
*
|
||||
* - Read-Write transfer: When @a rxSz and @ txSz members of @a xfer are non-zero.
|
||||
*
|
||||
* S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A]
|
||||
* S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P
|
||||
*
|
||||
*/
|
||||
void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive data in master mode
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param xfer : Pointer to a I2CM_XFER_T structure see notes below
|
||||
* @return Returns non-zero value on successful completion of transfer.
|
||||
* @note
|
||||
* This function operates same as Chip_I2CM_Xfer(), but is a blocking call.
|
||||
*/
|
||||
uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __I2CM_540XX_H_ */
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C slave driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Slave transfer state change handler */
|
||||
uint32_t Chip_I2CS_XferHandler(LPC_I2C_T *pI2C, const I2CS_XFER_T *xfers)
|
||||
{
|
||||
uint32_t done = 0, xferDone = 0;
|
||||
|
||||
uint8_t data;
|
||||
uint32_t state;
|
||||
|
||||
/* Transfer complete? */
|
||||
if ((Chip_I2C_GetPendingInt(pI2C) & I2C_INTENSET_SLVDESEL) != 0) {
|
||||
Chip_I2CS_ClearStatus(pI2C, I2C_STAT_SLVDESEL);
|
||||
xfers->slaveDone();
|
||||
xferDone = 1;
|
||||
}
|
||||
else {
|
||||
/* Determine the current I2C slave state */
|
||||
state = Chip_I2CS_GetSlaveState(pI2C);
|
||||
|
||||
switch (state) {
|
||||
case I2C_STAT_SLVCODE_ADDR: /* Slave address received */
|
||||
/* Get slave address that needs servicing */
|
||||
data = Chip_I2CS_GetSlaveAddr(pI2C, Chip_I2CS_GetSlaveMatchIndex(pI2C));
|
||||
|
||||
/* Call address callback */
|
||||
xfers->slaveStart(data);
|
||||
break;
|
||||
|
||||
case I2C_STAT_SLVCODE_RX: /* Data byte received, not used with DMA */
|
||||
/* Get received data */
|
||||
data = Chip_I2CS_ReadByte(pI2C);
|
||||
done = xfers->slaveRecv(data);
|
||||
break;
|
||||
|
||||
case I2C_STAT_SLVCODE_TX: /* Get byte that needs to be sent, or start DMA */
|
||||
/* Get data to send */
|
||||
done = xfers->slaveSend(&data);
|
||||
if (!((done == I2C_SLVCTL_SLVNACK) || (done == I2C_SLVCTL_SLVDMA))) {
|
||||
Chip_I2CS_WriteByte(pI2C, data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (done == I2C_SLVCTL_SLVNACK) {
|
||||
Chip_I2CS_SlaveNACK(pI2C);
|
||||
done = 1;
|
||||
}
|
||||
else if (done == I2C_SLVCTL_SLVDMA) {
|
||||
Chip_I2CS_SlaveEnableDMA(pI2C);
|
||||
}
|
||||
else {
|
||||
Chip_I2CS_SlaveContinue(pI2C);
|
||||
}
|
||||
|
||||
return xferDone;
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* @brief LPC540xx I2C slave driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __I2CS_540XX_H_
|
||||
#define __I2CS_540XX_H_
|
||||
|
||||
#include "i2c_common_540xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup I2CS_540XX CHIP: LPC540xx I2C slave-only driver
|
||||
* @ingroup I2C_540XX
|
||||
* This driver only works in slave mode.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief I2C slave service start callback
|
||||
* This callback is called from the I2C slave handler when an I2C slave address is
|
||||
* received and needs servicing. It's used to indicate the start of a slave transfer
|
||||
* that will happen on the slave bus.
|
||||
*/
|
||||
typedef void (*I2CSlaveXferStart)(uint8_t addr);
|
||||
|
||||
/** @brief I2C slave send data callback
|
||||
* This callback is called from the I2C slave handler when an I2C slave address needs
|
||||
* data to send.<br>
|
||||
* If you want to NAK the master, return I2C_SLVCTL_SLVNACK to the caller.
|
||||
* Return I2C_SLVCTL_SLVCONTINUE or 0 to the caller for normal non-DMA data transfer.
|
||||
* If you've setup a DMA descriptor for the transfer, return I2C_SLVCTL_SLVDMA to the caller.<br>
|
||||
*/
|
||||
typedef uint8_t (*I2CSlaveXferSend)(uint8_t *data);
|
||||
|
||||
/** @brief I2C slave receive data callback
|
||||
* This callback is called from the I2C slave handler when an I2C slave address has
|
||||
* receive data.<br>
|
||||
* If you want to NAK the master, return I2C_SLVCTL_SLVNACK to the caller.
|
||||
* Return I2C_SLVCTL_SLVCONTINUE or 0 to the caller for normal non-DMA data transfer.
|
||||
* If you've setup a DMA descriptor for the transfer, return I2C_SLVCTL_SLVDMA to the caller.<br>
|
||||
*/
|
||||
typedef uint8_t (*I2CSlaveXferRecv)(uint8_t data);
|
||||
|
||||
/** @brief I2C slave service done callback
|
||||
* This callback is called from the I2C slave handler when an I2C slave transfer is
|
||||
* completed. It's used to indicate the end of a slave transfer.
|
||||
*/
|
||||
typedef void (*I2CSlaveXferDone)(void);
|
||||
|
||||
/**
|
||||
* Slave transfer are performed using 4 callbacks. These 3 callbacks handle most I2C
|
||||
* slave transfer cases. When the slave is setup and a slave interrupt is receive
|
||||
* and processed with the Chip_I2CS_XferHandler() function in the I2C interrupt handler,
|
||||
* one of these 4 callbacks is called. The callbacks can be used for unsized transfers
|
||||
* from the master.
|
||||
*
|
||||
* When an address is received, the SlaveXferAddr() callback is called with the
|
||||
* received address. Only addresses enabled in the slave controller will be handled.
|
||||
* The slave controller can support up to 4 slave addresses.
|
||||
*
|
||||
* If the master is going to perform a read operation, the SlaveXferSend() callback
|
||||
* is called. Place the data byte to send in *data and return a value of 0 or
|
||||
* I2C_SLVCTL_SLVCONTINUE to the caller, or return a value o I2C_SLVCTL_SLVNACK to
|
||||
* NACK the master. If you are using DMA and have setup a DMA descriptor in the
|
||||
* callback, return I2C_SLVCTL_SLVDMA.<br>
|
||||
*
|
||||
* If the master performs a write operation, the SlaveXferRecv() callback is called
|
||||
* with the received data. Return a value of 0 or I2C_SLVCTL_SLVCONTINUE to the caller
|
||||
* to continue data transfer. Return I2C_SLVCTL_SLVNACK to NACk the master. If you
|
||||
* are using DMA and have setup a DMA descriptor in the callback, return
|
||||
* I2C_SLVCTL_SLVDMA.<br>
|
||||
*
|
||||
* Once the transfer completes, the SlaveXferDone() callback will be called.<br>
|
||||
*/
|
||||
typedef struct {
|
||||
I2CSlaveXferStart slaveStart; /*!< Called when an matching I2C slave address is received */
|
||||
I2CSlaveXferSend slaveSend; /*!< Called when a byte is needed to send to master */
|
||||
I2CSlaveXferRecv slaveRecv; /*!< Called when a byte is received from master */
|
||||
I2CSlaveXferDone slaveDone; /*!< Called when a slave transfer is complete */
|
||||
} I2CS_XFER_T;
|
||||
|
||||
/**
|
||||
* @brief Enable I2C slave interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note Do not call this function until the slave interface is fully configured.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_Enable(LPC_I2C_T *pI2C)
|
||||
{
|
||||
Chip_I2C_SetRegMask(&pI2C->CFG, I2C_CFG_MASK, I2C_CFG_SLVEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C slave interface
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_Disable(LPC_I2C_T *pI2C)
|
||||
{
|
||||
Chip_I2C_ClearRegMask(&pI2C->CFG, I2C_CFG_MASK, I2C_CFG_SLVEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C Status
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return I2C Status register value
|
||||
* @note This function returns the value of the status register.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_I2CS_GetStatus(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return pI2C->STAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C status bits (slave)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param clrStatus : Status bit to clear, must be I2C_STAT_SLVDESEL
|
||||
* @return Nothing
|
||||
* @note This function clears selected status flags.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_ClearStatus(LPC_I2C_T *pI2C, uint32_t clrStatus)
|
||||
{
|
||||
pI2C->STAT = clrStatus & I2C_STAT_SLVDESEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if I2C slave is pending
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Returns TRUE if the slave is pending else returns FALSE
|
||||
* @note
|
||||
*/
|
||||
STATIC INLINE bool Chip_I2CS_IsSlavePending(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_SLVPENDING) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if I2C slave is selected
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Returns TRUE if the slave is is selected, otherwise FALSE
|
||||
* @note
|
||||
*/
|
||||
STATIC INLINE bool Chip_I2CS_IsSlaveSelected(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_SLVSEL) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if I2C slave is deselected
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Returns TRUE if the slave is is deselected, otherwise FALSE
|
||||
* @note
|
||||
*/
|
||||
STATIC INLINE bool Chip_I2CS_IsSlaveDeSelected(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_SLVDESEL) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current state of the I2C slave
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return slave State Code, a value of type I2C_STAT_SLVCODE_*
|
||||
* @note After the slave is pending this state code tells the reason
|
||||
* for slave pending.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_I2CS_GetSlaveState(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_SLVSTATE) >> 9;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current slave address match index
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return slave match index, 0 - 3
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_I2CS_GetSlaveMatchIndex(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (pI2C->STAT & I2C_STAT_SLVIDX) >> 12;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slave Continue transfer operation (ACK)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function sets the slave controller to continue transmission.
|
||||
* This should be called only when slave is pending. The function writes a
|
||||
* complete value to slave Control register, ORing is not advised.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SlaveContinue(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->SLVCTL = I2C_SLVCTL_SLVCONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slave NACK operation
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function sets the slave controller to NAK the master.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SlaveNACK(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->SLVCTL = I2C_SLVCTL_SLVNACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable slave DMA operation
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function enables DMA mode for the slave controller. In DMA
|
||||
* mode, the 'continue' and 'NACK' operations aren't used and the I2C slave
|
||||
* controller will automatically NACK any bytes beyond the available DMA
|
||||
* buffer size.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SlaveEnableDMA(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->SLVCTL = I2C_SLVCTL_SLVDMA;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable slave DMA operation
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return Nothing
|
||||
* @note This function disables DMA mode for the slave controller.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SlaveDisableDMA(LPC_I2C_T *pI2C)
|
||||
{
|
||||
pI2C->SLVCTL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a single data byte through the I2C peripheral (slave)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param data : Byte to transmit
|
||||
* @return Nothing
|
||||
* @note This function attempts to place a byte into the I2C slave
|
||||
* Data Register
|
||||
*
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_WriteByte(LPC_I2C_T *pI2C, uint8_t data)
|
||||
{
|
||||
pI2C->SLVDAT = (uint32_t) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a single byte data from the I2C peripheral (slave)
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @return A single byte of data read
|
||||
* @note This function reads a byte from the I2C receive hold register
|
||||
* regardless of I2C state.
|
||||
*/
|
||||
STATIC INLINE uint8_t Chip_I2CS_ReadByte(LPC_I2C_T *pI2C)
|
||||
{
|
||||
return (uint8_t) (pI2C->SLVDAT & I2C_SLVDAT_DATAMASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a I2C slave address for slave operation
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param slvNum : Possible slave address number, between 0 - 3
|
||||
* @param slvAddr : Slave Address for the index (7-bits, bit 7 = 0)
|
||||
* @return Nothing
|
||||
* @note Setting a slave address also enables the slave address. Do
|
||||
* not 'pre-shift' the slave address.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SetSlaveAddr(LPC_I2C_T *pI2C, uint8_t slvNum, uint8_t slvAddr)
|
||||
{
|
||||
pI2C->SLVADR[slvNum] = (uint32_t) (slvAddr << 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a I2C programmed slave address
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param slvNum : Possible slave address number, between 0 - 3
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE uint8_t Chip_I2CS_GetSlaveAddr(LPC_I2C_T *pI2C, uint8_t slvNum)
|
||||
{
|
||||
return (pI2C->SLVADR[slvNum] >> 1) & 0x7F;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a I2C address
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param slvNum : Possible slave address number, between 0 - 3
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_EnableSlaveAddr(LPC_I2C_T *pI2C, uint8_t slvNum)
|
||||
{
|
||||
pI2C->SLVADR[slvNum] = (pI2C->SLVADR[slvNum] & I2C_SLVADR_MASK) & ~I2C_SLVADR_SADISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a I2C address
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param slvNum : Possible slave address number, between 0 - 3
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_DisableSlaveAddr(LPC_I2C_T *pI2C, uint8_t slvNum)
|
||||
{
|
||||
pI2C->SLVADR[slvNum] = (pI2C->SLVADR[slvNum] & I2C_SLVADR_MASK) | I2C_SLVADR_SADISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup slave qialifier address
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param extend : true to extend I2C slave detect address 0 range, or false to match to corresponding bits
|
||||
* @param slvAddr : Slave address qualifier, see SLVQUAL0 register in User Manual
|
||||
* @return Nothing
|
||||
* @note Do not 'pre-shift' the slave address.
|
||||
*/
|
||||
STATIC INLINE void Chip_I2CS_SetSlaveQual0(LPC_I2C_T *pI2C, bool extend, uint8_t slvNum)
|
||||
{
|
||||
slvNum = slvNum << 1;
|
||||
if (extend) {
|
||||
slvNum |= I2C_SLVQUAL_QUALMODE0;
|
||||
}
|
||||
|
||||
pI2C->SLVQUAL0 = slvNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slave transfer state change handler
|
||||
* @param pI2C : Pointer to selected I2C peripheral
|
||||
* @param xfers : Pointer to a I2CS_MULTI_XFER_T structure see notes below
|
||||
* @return Returns non-zero value on completion of transfer or NAK
|
||||
* @note See @ref I2CS_XFER_T for more information on this function. When using
|
||||
* this function, the I2C_INTENSET_SLVPENDING and I2C_INTENSET_SLVDESEL interrupts
|
||||
* should be enabled and setup in the I2C interrupt handler to call this function
|
||||
* when they fire.
|
||||
*/
|
||||
uint32_t Chip_I2CS_XferHandler(LPC_I2C_T *pI2C, const I2CS_XFER_T *xfers);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __I2CS_540XX_H_ */
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
STATIC void SPI_Send_Data_RxIgnore(LPC_SPI_T *pSPI,
|
||||
SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
|
||||
Chip_SPI_SendLastFrame_RxIgnore(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
|
||||
}
|
||||
else {
|
||||
Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
|
||||
}
|
||||
|
||||
pXfSetup->TxCnt++;
|
||||
}
|
||||
|
||||
STATIC void SPI_Send_Data(LPC_SPI_T *pSPI,
|
||||
SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
if (pXfSetup->TxCnt == (pXfSetup->Length - 1)) {
|
||||
Chip_SPI_SendLastFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt], pXfSetup->DataSize);
|
||||
}
|
||||
else {
|
||||
Chip_SPI_SendMidFrame(pSPI, pXfSetup->pTx[pXfSetup->TxCnt]);
|
||||
}
|
||||
|
||||
pXfSetup->TxCnt++;
|
||||
}
|
||||
|
||||
STATIC void SPI_Send_Dummy(LPC_SPI_T *pSPI,
|
||||
SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
if (pXfSetup->RxCnt == (pXfSetup->Length - 1)) {
|
||||
Chip_SPI_SendLastFrame(pSPI, 0x55, pXfSetup->DataSize);
|
||||
}
|
||||
else {
|
||||
Chip_SPI_SendMidFrame(pSPI, 0x55);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void SPI_Receive_Data(LPC_SPI_T *pSPI,
|
||||
SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
pXfSetup->pRx[pXfSetup->RxCnt] = Chip_SPI_ReceiveFrame(pSPI);
|
||||
pXfSetup->RxCnt++;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Calculate the Clock Rate Divider for SPI Peripheral */
|
||||
uint32_t Chip_SPI_CalClkRateDivider(LPC_SPI_T *pSPI, uint32_t bitRate)
|
||||
{
|
||||
uint32_t SPIClk;
|
||||
uint32_t DivVal = 1;
|
||||
|
||||
/* Get SPI clock rate */
|
||||
SPIClk = Chip_Clock_GetAsyncSysconClockRate(); /*The peripheral clock for both SPIs is the Async Syscon clock*/
|
||||
|
||||
DivVal = SPIClk / bitRate;
|
||||
|
||||
return DivVal;
|
||||
}
|
||||
|
||||
/* Initialize the SPI */
|
||||
void Chip_SPI_IF_Init(LPC_SPI_T *pSPI, SPI_MODECONFIG_T *pConfig)
|
||||
{
|
||||
uint32_t EnStat;
|
||||
|
||||
Chip_SPI_Init(pSPI);
|
||||
|
||||
EnStat = pSPI->CFG & SPI_CFG_SPI_EN;
|
||||
/* Disable before update CFG register */
|
||||
if (EnStat) {
|
||||
Chip_SPI_Disable(pSPI);
|
||||
}
|
||||
|
||||
/* SPI Configurate */
|
||||
pSPI->CFG = ((uint32_t) pConfig->ClockMode) | ((uint32_t) pConfig->DataOrder) | ((uint32_t) pConfig->Mode) |
|
||||
((uint32_t) pConfig->SSELPol);
|
||||
|
||||
if ( pConfig->Mode == SPI_CFG_MASTER_EN ) {
|
||||
/* Rate Divider setting */
|
||||
pSPI->DIV = SPI_DIV_VAL(pConfig->ClkDiv);
|
||||
}
|
||||
|
||||
/* Clear status flag*/
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_RXOV | SPI_STAT_TXUR | SPI_STAT_SSA | SPI_STAT_SSD);
|
||||
|
||||
/* Return the previous state */
|
||||
if (EnStat) {
|
||||
Chip_SPI_Enable(pSPI);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable/Enable Interrupt */
|
||||
void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState)
|
||||
{
|
||||
if (NewState == ENABLE) {
|
||||
Chip_SPI_EnableInts(pSPI, IntMask);
|
||||
}
|
||||
else {
|
||||
Chip_SPI_DisableInts(pSPI, IntMask);
|
||||
}
|
||||
}
|
||||
|
||||
/*Send and Receive SPI Data */
|
||||
uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
uint32_t Status;
|
||||
/* Clear status */
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_RXOV | SPI_STAT_TXUR | SPI_STAT_SSA | SPI_STAT_SSD);
|
||||
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
|
||||
pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
|
||||
while ((pXfSetup->TxCnt < pXfSetup->Length) ||
|
||||
(pXfSetup->RxCnt < pXfSetup->Length)) {
|
||||
Status = Chip_SPI_GetStatus(pSPI);
|
||||
|
||||
/* In case of TxReady */
|
||||
if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
|
||||
SPI_Send_Data(pSPI, pXfSetup);
|
||||
}
|
||||
|
||||
/*In case of Rx ready */
|
||||
if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
|
||||
SPI_Receive_Data(pSPI, pXfSetup);
|
||||
}
|
||||
}
|
||||
/* Check error */
|
||||
if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
|
||||
return 0;
|
||||
}
|
||||
return pXfSetup->TxCnt;
|
||||
}
|
||||
|
||||
uint32_t Chip_SPI_WriteFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
/* Clear status */
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_RXOV | SPI_STAT_TXUR | SPI_STAT_SSA | SPI_STAT_SSD);
|
||||
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
|
||||
pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
|
||||
while (pXfSetup->TxCnt < pXfSetup->Length) {
|
||||
/* Wait for TxReady */
|
||||
while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
|
||||
|
||||
SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
|
||||
|
||||
}
|
||||
|
||||
/* Make sure the last frame sent completely*/
|
||||
while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD)) {}
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSD);
|
||||
|
||||
/* Check overrun error */
|
||||
if (Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXUR) {
|
||||
return 0;
|
||||
}
|
||||
return pXfSetup->TxCnt;
|
||||
}
|
||||
|
||||
uint32_t Chip_SPI_ReadFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
/* Clear status */
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_RXOV | SPI_STAT_TXUR | SPI_STAT_SSA | SPI_STAT_SSD);
|
||||
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
|
||||
pXfSetup->TxCnt = pXfSetup->RxCnt = 0;
|
||||
while (pXfSetup->RxCnt < pXfSetup->Length) {
|
||||
/* Wait for TxReady */
|
||||
while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY)) {}
|
||||
|
||||
SPI_Send_Dummy(pSPI, pXfSetup);
|
||||
|
||||
/* Wait for receive data */
|
||||
while (!(Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY)) {}
|
||||
|
||||
SPI_Receive_Data(pSPI, pXfSetup);
|
||||
|
||||
}
|
||||
/* Check overrun error */
|
||||
if (Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
|
||||
return 0;
|
||||
}
|
||||
return pXfSetup->RxCnt;
|
||||
}
|
||||
|
||||
/* SPI Interrupt Read/Write with 8-bit frame width */
|
||||
Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
|
||||
{
|
||||
uint32_t Status;
|
||||
|
||||
Status = Chip_SPI_GetStatus(pSPI);
|
||||
/* Check error in INTSTAT register */
|
||||
if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (pXfSetup->TxCnt == 0) {
|
||||
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, SPI_TXCTL_ASSERT_SSEL | SPI_TXCTL_EOF);
|
||||
}
|
||||
|
||||
if (pXfSetup->pRx == NULL) {
|
||||
if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
|
||||
SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* check if Tx ready */
|
||||
if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
|
||||
SPI_Send_Data(pSPI, pXfSetup);
|
||||
}
|
||||
|
||||
/* check if RX FIFO contains data */
|
||||
if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
|
||||
SPI_Receive_Data(pSPI, pXfSetup);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// end file
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_540XX_H_
|
||||
#define __SPI_540XX_H_
|
||||
|
||||
#include "spi_common_540xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup SPI_LEGACY 540XX CHIP: LPC540XX SPI legacy driver
|
||||
* @ingroup SPI_COMMON_540XX
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SLAVE0 = ((~(1 << 0)) & 0xf),
|
||||
SLAVE1 = ((~(1 << 1)) & 0xf),
|
||||
SLAVE2 = ((~(1 << 2)) & 0xf),
|
||||
SLAVE3 = ((~(1 << 3)) & 0xf)
|
||||
} SLAVE_T;
|
||||
|
||||
#define SPI_TXDATCTL_SSELN(s) ((s) << 16)
|
||||
|
||||
/** @brief SPI Mode*/
|
||||
typedef enum {
|
||||
SPI_MODE_MASTER = SPI_CFG_MASTER_EN, /* Master Mode */
|
||||
SPI_MODE_SLAVE = SPI_CFG_SLAVE_EN, /* Slave Mode */
|
||||
} SPI_MODE_T;
|
||||
|
||||
/** @brief SPI Data Order Mode*/
|
||||
typedef enum IP_SPI_DATA_ORDER {
|
||||
SPI_DATA_MSB_FIRST = SPI_CFG_MSB_FIRST_EN, /* Standard Order */
|
||||
SPI_DATA_LSB_FIRST = SPI_CFG_LSB_FIRST_EN, /* Reverse Order */
|
||||
} SPI_DATA_ORDER_T;
|
||||
|
||||
/** @brief SPI SSEL Polarity definition*/
|
||||
typedef enum IP_SPI_SSEL_POL {
|
||||
SPI_SSEL_ACTIVE_LO = SPI_CFG_SPOL_LO, /* SSEL is active Low*/
|
||||
SPI_SSEL_ACTIVE_HI = SPI_CFG_SPOL_HI, /* SSEL is active High */
|
||||
} SPI_SSEL_POL_T;
|
||||
|
||||
/**
|
||||
* @brief SPI Configure Struct
|
||||
*/
|
||||
typedef struct {
|
||||
SPI_MODE_T Mode; /* Mode Select */
|
||||
SPI_CLOCK_MODE_T ClockMode; /* CPHA CPOL Select */
|
||||
SPI_DATA_ORDER_T DataOrder; /* MSB/LSB First */
|
||||
SPI_SSEL_POL_T SSELPol; /* SSEL Polarity Select */
|
||||
uint16_t ClkDiv; /* SPI Clock Divider Value */
|
||||
} SPI_MODECONFIG_T;
|
||||
|
||||
/**
|
||||
* @brief SPI data setup structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t *pTx; /**< Pointer to data buffer*/
|
||||
uint32_t TxCnt;/* Transmit Counter */
|
||||
uint16_t *pRx; /**< Pointer to data buffer*/
|
||||
uint32_t RxCnt;/* Transmit Counter */
|
||||
uint32_t Length; /**< Data Length*/
|
||||
uint16_t DataSize; /** < The size of a frame (1-16)*/
|
||||
uint32_t completion_flag;
|
||||
} SPI_DATA_SETUP_T;
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param pConfig : SPI Configuration
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPI_IF_Init(LPC_SPI_T *pSPI, SPI_MODECONFIG_T *pConfig);
|
||||
|
||||
/**
|
||||
* @brief Calculate the divider for SPI clock
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param bitRate : Expected clock rate
|
||||
* @return Divider value
|
||||
*/
|
||||
uint32_t Chip_SPI_CalClkRateDivider(LPC_SPI_T *pSPI, uint32_t bitRate);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable SPI interrupt
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param IntMask : Interrupt mask
|
||||
* @param NewState : ENABLE or DISABLE interrupt
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPI_Int_Cmd(LPC_SPI_T *pSPI, uint32_t IntMask, FunctionalState NewState);
|
||||
|
||||
/**
|
||||
* @brief Set control information including SSEL, EOT, EOF RXIGNORE and FLEN
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Flen : Data size (1-16)
|
||||
* @param Flag : Flag control (Or-ed values of SPI_TXCTL_*)
|
||||
* @note The control information has no effect unless data is later written to TXDAT
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetControlInfo(LPC_SPI_T *pSPI, uint8_t Flen, uint32_t Flag)
|
||||
{
|
||||
pSPI->TXCTRL = Flag | SPI_TXDATCTL_FLEN(Flen - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the first Frame of a transfer (Rx Ignore)
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Data : Transmit data
|
||||
* @param DataSize : Data Size (1-16)
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SendFirstFrame_RxIgnore(LPC_SPI_T *pSPI, uint16_t Data, uint8_t DataSize)
|
||||
{
|
||||
pSPI->TXDATCTL = SPI_TXDATCTL_ASSERT_SSEL | SPI_TXDATCTL_EOF | SPI_TXDATCTL_RXIGNORE | SPI_TXDATCTL_FLEN(
|
||||
DataSize - 1) | SPI_TXDATCTL_DATA(Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the first Frame of a transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Data : Transmit data
|
||||
* @param DataSize : Data Size (1-16)
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SendFirstFrame(LPC_SPI_T *pSPI, uint16_t Data, uint8_t DataSize)
|
||||
{
|
||||
pSPI->TXDATCTL = SPI_TXDATCTL_ASSERT_SSEL | SPI_TXDATCTL_EOF | SPI_TXDATCTL_FLEN(DataSize - 1) | SPI_TXDATCTL_DATA(
|
||||
Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the middle Frame of a transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Data : Transmit data
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SendMidFrame(LPC_SPI_T *pSPI, uint16_t Data)
|
||||
{
|
||||
pSPI->TXDAT = SPI_TXDAT_DATA(Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the last Frame of a transfer (Rx Ignore)
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Data : Transmit data
|
||||
* @param DataSize : Data Size (1-16)
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SendLastFrame_RxIgnore(LPC_SPI_T *pSPI, uint16_t Data, uint8_t DataSize)
|
||||
{
|
||||
pSPI->TXDATCTL = SPI_TXDATCTL_ASSERT_SSEL | SPI_TXDATCTL_EOF | SPI_TXDATCTL_EOT | SPI_TXDATCTL_RXIGNORE |
|
||||
SPI_TXDATCTL_FLEN(DataSize - 1) | SPI_TXDATCTL_DATA(Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the last Frame of a transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Data : Transmit data
|
||||
* @param DataSize : Data Size (1-16)
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SendLastFrame(LPC_SPI_T *pSPI, uint16_t Data, uint8_t DataSize)
|
||||
{
|
||||
pSPI->TXDATCTL = SPI_TXDATCTL_ASSERT_SSEL | SPI_TXDATCTL_EOF | SPI_TXDATCTL_EOT |
|
||||
SPI_TXDATCTL_FLEN(DataSize - 1) | SPI_TXDATCTL_DATA(Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data received
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Receive data
|
||||
*/
|
||||
STATIC INLINE uint16_t Chip_SPI_ReceiveFrame(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return SPI_RXDAT_DATA(pSPI->RXDAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI Interrupt Read/Write
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param xf_setup : Pointer to a SPI_DATA_SETUP_T structure that contains specified
|
||||
* information about transmit/receive data configuration
|
||||
* @return SUCCESS or ERROR
|
||||
*/
|
||||
Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *xf_setup);
|
||||
|
||||
/**
|
||||
* @brief SPI Polling Read/Write in blocking mode
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param pXfSetup : Pointer to a SPI_DATA_SETUP_T structure that contains specified
|
||||
* information about transmit/receive data configuration
|
||||
* @return Actual data length has been transferred
|
||||
* @note
|
||||
* This function can be used in both master and slave mode. It starts with writing phase and after that,
|
||||
* a reading phase is generated to read any data available in RX_FIFO. All needed information is prepared
|
||||
* through xf_setup param.
|
||||
*/
|
||||
uint32_t Chip_SPI_RWFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup);
|
||||
|
||||
/**
|
||||
* @brief SPI Polling Write in blocking mode
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param pXfSetup :Pointer to a SPI_DATA_SETUP_T structure that contains specified
|
||||
* information about transmit/receive data configuration
|
||||
* @return Actual data length has been transferred
|
||||
* @note
|
||||
* This function can be used in both master and slave mode. First, a writing operation will send
|
||||
* the needed data. After that, a dummy reading operation is generated to clear data buffer
|
||||
*/
|
||||
uint32_t Chip_SPI_WriteFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup);
|
||||
|
||||
/**
|
||||
* @brief SPI Polling Read in blocking mode
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @param pXfSetup :Pointer to a SPI_DATA_SETUP_T structure that contains specified
|
||||
* information about transmit/receive data configuration
|
||||
* @return Actual data length has been read
|
||||
* @note
|
||||
* This function can be used in both master and slave mode. First, a writing operation will send
|
||||
* the needed data. After that, a dummy reading operation is generated to clear data buffer
|
||||
*/
|
||||
uint32_t Chip_SPI_ReadFrames_Blocking(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SPI_540XX_H_ */
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Return clock for the passed peripheral */
|
||||
static CHIP_SYSCON_CLOCK_T getSPIClk(LPC_SPI_T *pSPI)
|
||||
{
|
||||
if (pSPI == LPC_SPI0) {
|
||||
return SYSCON_CLOCK_SPI0;
|
||||
}
|
||||
return SYSCON_CLOCK_SPI1;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Initialize the SPI */
|
||||
void Chip_SPI_Init(LPC_SPI_T *pSPI)
|
||||
{
|
||||
/* Enable SPI clock and reset IP */
|
||||
Chip_Clock_EnablePeriphClock(getSPIClk(pSPI));
|
||||
if (pSPI == LPC_SPI1) {
|
||||
Chip_SYSCON_PeriphReset(RESET_SPI1);
|
||||
}
|
||||
else {
|
||||
Chip_SYSCON_PeriphReset(RESET_SPI0);
|
||||
}
|
||||
}
|
||||
|
||||
/* De-initializes the SPI peripheral */
|
||||
void Chip_SPI_DeInit(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_Disable(pSPI);
|
||||
Chip_Clock_DisablePeriphClock(getSPIClk(pSPI));
|
||||
}
|
||||
|
||||
/* Set SPI CFG register values */
|
||||
void Chip_SPI_SetCFGRegBits(LPC_SPI_T *pSPI, uint32_t bits)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Mask off bits that are write as 0, read as undefined */
|
||||
reg = pSPI->CFG & SPI_CFG_BITMASK;
|
||||
|
||||
/* Update CFG register with only selected bits enabled */
|
||||
pSPI->CFG = reg | bits;
|
||||
}
|
||||
|
||||
/* Clear SPI CFG register values */
|
||||
void Chip_SPI_ClearCFGRegBits(LPC_SPI_T *pSPI, uint32_t bits)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Mask off bits that are write as 0, read as undefined */
|
||||
reg = pSPI->CFG & SPI_CFG_BITMASK;
|
||||
|
||||
/* Update CFG register with only selected bits disabled */
|
||||
pSPI->CFG = reg & ~bits;
|
||||
}
|
||||
|
||||
/* Enable SPI master mode */
|
||||
void Chip_SPI_EnableMasterMode(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_SetCFGRegBits(pSPI, SPI_CFG_MASTER_EN);
|
||||
|
||||
/* Deassert all chip selects, only in master mode */
|
||||
pSPI->TXCTRL = SPI_TXDATCTL_DEASSERT_ALL;
|
||||
}
|
||||
|
||||
/* Setup SAPI configuration */
|
||||
void Chip_SPI_ConfigureSPI(LPC_SPI_T *pSPI, SPI_CFGSETUP_T *pCFG)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Get register and mask off config bits this function alters */
|
||||
reg = pSPI->CFG & ~(SPI_CFG_MASTER_EN | SPI_CFG_LSB_FIRST_EN |
|
||||
SPI_CFG_CPHA_SECOND | SPI_CFG_CPOL_HI);
|
||||
|
||||
if (pCFG->master) {
|
||||
reg |= SPI_CFG_MASTER_EN;
|
||||
}
|
||||
if (pCFG->lsbFirst) {
|
||||
reg |= SPI_CFG_LSB_FIRST_EN;
|
||||
}
|
||||
reg |= (uint32_t) pCFG->mode;
|
||||
|
||||
Chip_SPI_SetCFGRegBits(pSPI, reg);
|
||||
|
||||
/* Deassert all chip selects, only in master mode */
|
||||
pSPI->TXCTRL = SPI_TXDATCTL_DEASSERT_ALL;
|
||||
}
|
||||
|
||||
/* Flush FIFOs */
|
||||
void Chip_SPI_FlushFifos(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_Disable(pSPI);
|
||||
Chip_SPI_Enable(pSPI);
|
||||
}
|
||||
|
||||
/* Set SPI TXCTRL register control options */
|
||||
void Chip_SPI_SetTXCTRLRegBits(LPC_SPI_T *pSPI, uint32_t bits)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
|
||||
pSPI->TXCTRL = reg | bits;
|
||||
}
|
||||
|
||||
/* Clear SPI TXCTRL register control options */
|
||||
void Chip_SPI_ClearTXCTRLRegBits(LPC_SPI_T *pSPI, uint32_t bits)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
|
||||
pSPI->TXCTRL = reg & ~bits;
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI common functions and definitions
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_COMMON_540XX_H_
|
||||
#define __SPI_COMMON_540XX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup SPI_COMMON_540XX CHIP: LPC540XX SPI common functions and definitions
|
||||
* @ingroup CHIP_540XX_Drivers
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief SPI register block structure
|
||||
*/
|
||||
typedef struct { /*!< SPI Structure */
|
||||
__IO uint32_t CFG; /*!< SPI Configuration register */
|
||||
__IO uint32_t DLY; /*!< SPI Delay register */
|
||||
__IO uint32_t STAT; /*!< SPI Status register */
|
||||
__IO uint32_t INTENSET; /*!< SPI Interrupt Enable Set register */
|
||||
__O uint32_t INTENCLR; /*!< SPI Interrupt Enable Clear register */
|
||||
__I uint32_t RXDAT; /*!< SPI Receive Data register */
|
||||
__IO uint32_t TXDATCTL; /*!< SPI Transmit Data with Control register */
|
||||
__IO uint32_t TXDAT; /*!< SPI Transmit Data register */
|
||||
__IO uint32_t TXCTRL; /*!< SPI Transmit Control register */
|
||||
__IO uint32_t DIV; /*!< SPI clock Divider register */
|
||||
__I uint32_t INTSTAT; /*!< SPI Interrupt Status register */
|
||||
} LPC_SPI_T;
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Configuration register
|
||||
*/
|
||||
#define SPI_CFG_BITMASK (0xFBD) /** SPI register bit mask */
|
||||
#define SPI_CFG_SPI_EN (1 << 0) /** SPI Slave Mode Select */
|
||||
#define SPI_CFG_SLAVE_EN (0 << 0) /** SPI Master Mode Select */
|
||||
#define SPI_CFG_MASTER_EN (1 << 2) /** SPI MSB First mode enable */
|
||||
#define SPI_CFG_MSB_FIRST_EN (0 << 3) /** SPI LSB First mode enable */
|
||||
#define SPI_CFG_LSB_FIRST_EN (1 << 3) /** SPI Clock Phase Select */
|
||||
#define SPI_CFG_CPHA_FIRST (0 << 4) /** Capture data on the first edge, Change data on the following edge */
|
||||
#define SPI_CFG_CPHA_SECOND (1 << 4) /** SPI Clock Polarity Select */
|
||||
#define SPI_CFG_CPOL_LO (0 << 5) /** The rest state of the clock (between frames) is low. */
|
||||
#define SPI_CFG_CPOL_HI (1 << 5) /** The rest state of the clock (between frames) is high. */
|
||||
#define SPI_CFG_LBM_EN (1 << 7) /** SPI control 1 loopback mode enable */
|
||||
#define SPI_CFG_SPOL_LO (0 << 8) /** SPI SSEL0 Polarity Select */
|
||||
#define SPI_CFG_SPOL_HI (1 << 8) /** SSEL0 is active High */
|
||||
#define SPI_CFG_SPOLNUM_HI(n) (1 << ((n) + 8)) /** SSELN is active High, selects 0 - 3 */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Delay register
|
||||
*/
|
||||
#define SPI_DLY_BITMASK (0xFFFF) /** SPI DLY Register Mask */
|
||||
#define SPI_DLY_PRE_DELAY(n) (((n) & 0x0F) << 0) /** Time in SPI clocks between SSEL assertion and the beginning of a data frame */
|
||||
#define SPI_DLY_POST_DELAY(n) (((n) & 0x0F) << 4) /** Time in SPI clocks between the end of a data frame and SSEL deassertion. */
|
||||
#define SPI_DLY_FRAME_DELAY(n) (((n) & 0x0F) << 8) /** Minimum time in SPI clocks between adjacent data frames. */
|
||||
#define SPI_DLY_TRANSFER_DELAY(n) (((n) & 0x0F) << 12) /** Minimum time in SPI clocks that the SSEL is deasserted between transfers. */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Status register
|
||||
*/
|
||||
#define SPI_STAT_BITMASK (0x1FF) /** SPI STAT Register BitMask */
|
||||
#define SPI_STAT_RXRDY (1 << 0) /** Receiver Ready Flag */
|
||||
#define SPI_STAT_TXRDY (1 << 1) /** Transmitter Ready Flag */
|
||||
#define SPI_STAT_RXOV (1 << 2) /** Receiver Overrun interrupt flag */
|
||||
#define SPI_STAT_TXUR (1 << 3) /** Transmitter Underrun interrupt flag (In Slave Mode only) */
|
||||
#define SPI_STAT_SSA (1 << 4) /** Slave Select Assert */
|
||||
#define SPI_STAT_SSD (1 << 5) /** Slave Select Deassert */
|
||||
#define SPI_STAT_STALLED (1 << 6) /** Stalled status flag */
|
||||
#define SPI_STAT_EOT (1 << 7) /** End Transfer flag */
|
||||
#define SPI_STAT_MSTIDLE (1 << 8) /** Idle status flag */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Interrupt Enable read and Set register
|
||||
*/
|
||||
#define SPI_INTENSET_BITMASK (0x3F) /** SPI INTENSET Register BitMask */
|
||||
#define SPI_INTENSET_RXDYEN (1 << 0) /** Enable Interrupt when receiver data is available */
|
||||
#define SPI_INTENSET_TXDYEN (1 << 1) /** Enable Interrupt when the transmitter holding register is available. */
|
||||
#define SPI_INTENSET_RXOVEN (1 << 2) /** Enable Interrupt when a receiver overrun occurs */
|
||||
#define SPI_INTENSET_TXUREN (1 << 3) /** Enable Interrupt when a transmitter underrun occurs (In Slave Mode Only)*/
|
||||
#define SPI_INTENSET_SSAEN (1 << 4) /** Enable Interrupt when the Slave Select is asserted.*/
|
||||
#define SPI_INTENSET_SSDEN (1 << 5) /** Enable Interrupt when the Slave Select is deasserted..*/
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Interrupt Enable Clear register
|
||||
*/
|
||||
#define SPI_INTENCLR_BITMASK (0x3F) /** SPI INTENCLR Register BitMask */
|
||||
#define SPI_INTENCLR_RXDYEN (1 << 0) /** Disable Interrupt when receiver data is available */
|
||||
#define SPI_INTENCLR_TXDYEN (1 << 1) /** Disable Interrupt when the transmitter holding register is available. */
|
||||
#define SPI_INTENCLR_RXOVEN (1 << 2) /** Disable Interrupt when a receiver overrun occurs */
|
||||
#define SPI_INTENCLR_TXUREN (1 << 3) /** Disable Interrupt when a transmitter underrun occurs (In Slave Mode Only) */
|
||||
#define SPI_INTENCLR_SSAEN (1 << 4) /** Disable Interrupt when the Slave Select is asserted. */
|
||||
#define SPI_INTENCLR_SSDEN (1 << 5) /** Disable Interrupt when the Slave Select is deasserted.. */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Receiver Data register
|
||||
*/
|
||||
#define SPI_RXDAT_BITMASK (0x1FFFFF) /** SPI RXDAT Register BitMask */
|
||||
#define SPI_RXDAT_DATA(n) ((n) & 0xFFFF) /** Receiver Data */
|
||||
#define SPI_RXDAT_RXSSELN_ACTIVE (0 << 16) /** The state of SSEL pin is active */
|
||||
#define SPI_RXDAT_RXSSELN_INACTIVE ((1 << 16) /** The state of SSEL pin is inactive */
|
||||
#define SPI_RXDAT_RXSSELNUM_INACTIVE(n) (1 << ((n) + 16)) /** The state of SSELN pin is inactive */
|
||||
#define SPI_RXDAT_SOT (1 << 20) /** Start of Transfer flag */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Transmitter Data and Control register
|
||||
*/
|
||||
#define SPI_TXDATCTL_BITMASK (0xF7FFFFF) /** SPI TXDATCTL Register BitMask */
|
||||
#define SPI_TXDATCTL_DATA(n) ((n) & 0xFFFF) /** SPI Transmit Data */
|
||||
#define SPI_TXDATCTL_CTRLMASK (0xF7F0000) /** SPI TXDATCTL Register BitMask for control bits only */
|
||||
#define SPI_TXDATCTL_ASSERT_SSEL (0 << 16) /** Assert SSEL0 pin */
|
||||
#define SPI_TXDATCTL_DEASSERT_SSEL (1 << 16) /** Deassert SSEL0 pin */
|
||||
#define SPI_TXDATCTL_DEASSERTNUM_SSEL(n) (1 << ((n) + 16)) /** Deassert SSELN pin */
|
||||
#define SPI_TXDATCTL_DEASSERT_ALL (0xF << 16) /** Deassert all SSEL pins */
|
||||
#define SPI_TXDATCTL_EOT (1 << 20) /** End of Transfer flag (TRANSFER_DELAY is applied after sending the current frame) */
|
||||
#define SPI_TXDATCTL_EOF (1 << 21) /** End of Frame flag (FRAME_DELAY is applied after sending the current part) */
|
||||
#define SPI_TXDATCTL_RXIGNORE (1 << 22) /** Receive Ignore Flag */
|
||||
#define SPI_TXDATCTL_FLEN(n) (((n) & 0x0F) << 24) /** Frame length - 1 */
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Transmitter Data Register
|
||||
*/
|
||||
#define SPI_TXDAT_DATA(n) ((n) & 0xFFFF) /** SPI Transmit Data */
|
||||
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Transmitter Control register
|
||||
*/
|
||||
#define SPI_TXCTL_BITMASK (0xF7F0000) /** SPI TXDATCTL Register BitMask */
|
||||
#define SPI_TXCTL_ASSERT_SSEL (0 << 16) /** Assert SSEL0 pin */
|
||||
#define SPI_TXCTL_DEASSERT_SSEL (1 << 16) /** Deassert SSEL0 pin */
|
||||
#define SPI_TXCTL_DEASSERTNUM_SSEL(n) (1 << ((n) + 16)) /** Deassert SSELN pin */
|
||||
#define SPI_TXDATCTL_DEASSERT_ALL (0xF << 16) /** Deassert all SSEL pins */
|
||||
#define SPI_TXCTL_EOT (1 << 20) /** End of Transfer flag (TRANSFER_DELAY is applied after sending the current frame) */
|
||||
#define SPI_TXCTL_EOF (1 << 21) /** End of Frame flag (FRAME_DELAY is applied after sending the current part) */
|
||||
#define SPI_TXCTL_RXIGNORE (1 << 22) /** Receive Ignore Flag */
|
||||
#define SPI_TXCTL_FLEN(n) ((((n) - 1) & 0x0F) << 24) /** Frame length, 0 - 16 */
|
||||
#define SPI_TXCTL_FLENMASK (0xF << 24) /** Frame length mask */
|
||||
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Divider register
|
||||
*/
|
||||
#define SPI_DIV_VAL(n) ((n) & 0xFFFF) /** Rate divider value mask (In Master Mode only)*/
|
||||
|
||||
/**
|
||||
* Macro defines for SPI Interrupt Status register
|
||||
*/
|
||||
#define SPI_INTSTAT_BITMASK (0x3F) /** SPI INTSTAT Register Bitmask */
|
||||
#define SPI_INTSTAT_RXRDY (1 << 0) /** Receiver Ready Flag */
|
||||
#define SPI_INTSTAT_TXRDY (1 << 1) /** Transmitter Ready Flag */
|
||||
#define SPI_INTSTAT_RXOV (1 << 2) /** Receiver Overrun interrupt flag */
|
||||
#define SPI_INTSTAT_TXUR (1 << 3) /** Transmitter Underrun interrupt flag (In Slave Mode only) */
|
||||
#define SPI_INTSTAT_SSA (1 << 4) /** Slave Select Assert */
|
||||
#define SPI_INTSTAT_SSD (1 << 5) /** Slave Select Deassert */
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI
|
||||
* @param pSPI : The base SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPI_Init(LPC_SPI_T *pSPI);
|
||||
|
||||
/**
|
||||
* @brief Disable SPI operation
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note The SPI controller is disabled.
|
||||
*/
|
||||
void Chip_SPI_DeInit(LPC_SPI_T *pSPI);
|
||||
|
||||
/**
|
||||
* @brief Set SPI CFG register values
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param bits : CFG register bits to set, amd OR'ed value of SPI_CFG_* definitions
|
||||
* @return Nothing
|
||||
* @note This function safely sets only the selected bits in the SPI CFG register.
|
||||
* It can be used to enable multiple bits at once.
|
||||
*/
|
||||
void Chip_SPI_SetCFGRegBits(LPC_SPI_T *pSPI, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Clear SPI CFG register values
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param bits : CFG register bits to clear, amd OR'ed value of SPI_CFG_* definitions
|
||||
* @return Nothing
|
||||
* @note This function safely clears only the selected bits in the SPI CFG register.
|
||||
* It can be used to disable multiple bits at once.
|
||||
*/
|
||||
void Chip_SPI_ClearCFGRegBits(LPC_SPI_T *pSPI, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Enable SPI peripheral
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_Enable(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_SetCFGRegBits(pSPI, SPI_CFG_SPI_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable SPI peripheral
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_Disable(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, SPI_CFG_SPI_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable SPI master mode
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note SPI slave mode will be disabled with this call. All SPI SSEL
|
||||
* lines will also be deasserted.
|
||||
*/
|
||||
void Chip_SPI_EnableMasterMode(LPC_SPI_T *pSPI);
|
||||
|
||||
/**
|
||||
* @brief Enable SPI slave mode
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note SPI master mode will be disabled with this call.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_EnableSlaveMode(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, SPI_CFG_MASTER_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable LSB First transfers
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_EnableLSBFirst(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_SetCFGRegBits(pSPI, SPI_CFG_LSB_FIRST_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable MSB First transfers
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_EnableMSBFirst(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, SPI_CFG_LSB_FIRST_EN);
|
||||
}
|
||||
|
||||
/** @brief SPI Clock Mode*/
|
||||
typedef enum IP_SPI_CLOCK_MODE {
|
||||
SPI_CLOCK_CPHA0_CPOL0 = SPI_CFG_CPOL_LO | SPI_CFG_CPHA_FIRST, /**< CPHA = 0, CPOL = 0 */
|
||||
SPI_CLOCK_MODE0 = SPI_CLOCK_CPHA0_CPOL0, /**< Alias for CPHA = 0, CPOL = 0 */
|
||||
SPI_CLOCK_CPHA1_CPOL0 = SPI_CFG_CPOL_LO | SPI_CFG_CPHA_SECOND, /**< CPHA = 0, CPOL = 1 */
|
||||
SPI_CLOCK_MODE1 = SPI_CLOCK_CPHA1_CPOL0, /**< Alias for CPHA = 0, CPOL = 1 */
|
||||
SPI_CLOCK_CPHA0_CPOL1 = SPI_CFG_CPOL_HI | SPI_CFG_CPHA_FIRST, /**< CPHA = 1, CPOL = 0 */
|
||||
SPI_CLOCK_MODE2 = SPI_CLOCK_CPHA0_CPOL1, /**< Alias for CPHA = 1, CPOL = 0 */
|
||||
SPI_CLOCK_CPHA1_CPOL1 = SPI_CFG_CPOL_HI | SPI_CFG_CPHA_SECOND, /**< CPHA = 1, CPOL = 1 */
|
||||
SPI_CLOCK_MODE3 = SPI_CLOCK_CPHA1_CPOL1, /**< Alias for CPHA = 1, CPOL = 1 */
|
||||
} SPI_CLOCK_MODE_T;
|
||||
|
||||
/**
|
||||
* @brief Set SPI mode
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param mode : SPI mode to set the SPI interface to
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetSPIMode(LPC_SPI_T *pSPI, SPI_CLOCK_MODE_T mode)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, (SPI_CFG_CPOL_HI | SPI_CFG_CPHA_SECOND));
|
||||
Chip_SPI_SetCFGRegBits(pSPI, (uint32_t) mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set polarity on the SPI chip select high
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param csNum : Chip select number, 0 - 3
|
||||
* @return Nothing
|
||||
* @note SPI chip select polarity is active high.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetCSPolHigh(LPC_SPI_T *pSPI, uint8_t csNum)
|
||||
{
|
||||
Chip_SPI_SetCFGRegBits(pSPI, SPI_CFG_SPOLNUM_HI(csNum));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set polarity on the SPI chip select low
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param csNum : Chip select number, 0 - 3
|
||||
* @return Nothing
|
||||
* @note SPI chip select polarity is active low.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetCSPolLow(LPC_SPI_T *pSPI, uint8_t csNum)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, SPI_CFG_SPOLNUM_HI(csNum));
|
||||
}
|
||||
|
||||
/** SPI configuration structure used for setting up master/slave mode, LSB or
|
||||
* MSB first, and SPI mode in a single function call. */
|
||||
typedef struct {
|
||||
uint32_t master : 8; /* Set to non-0 value to use master mode, 0 for slave */
|
||||
uint32_t lsbFirst : 8; /* Set to non-0 value to send LSB first, 0 for MSB first */
|
||||
SPI_CLOCK_MODE_T mode : 8; /* Mode selection */
|
||||
uint32_t reserved : 8; /* Reserved, for alignment only */
|
||||
} SPI_CFGSETUP_T;
|
||||
|
||||
/**
|
||||
* @brief Setup SPI configuration
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param pCFG : Pointer to SPI configuration structure
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPI_ConfigureSPI(LPC_SPI_T *pSPI, SPI_CFGSETUP_T *pCFG);
|
||||
|
||||
/**
|
||||
* @brief Get the current status of SPI controller
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return SPI Status (Or-ed bit value of SPI_STAT_*)
|
||||
* @note Mask the return value with a value of type SPI_STAT_* to determine
|
||||
* if that status is active.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_SPI_GetStatus(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return pSPI->STAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear SPI status
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param Flag : Clear Flag (Or-ed bit value of SPI_STAT_*)
|
||||
* @return Nothing
|
||||
* @note Only SPI_STAT_RXOV, SPI_STAT_TXUR, SPI_STAT_SSA, and
|
||||
* SPI_STAT_SSD statuses can be cleared.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_ClearStatus(LPC_SPI_T *pSPI, uint32_t Flag)
|
||||
{
|
||||
pSPI->STAT = Flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a SPI interrupt
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param intMask : Or'ed value of SPI_INTENSET_* values to enable
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_EnableInts(LPC_SPI_T *pSPI, uint32_t Flag)
|
||||
{
|
||||
pSPI->INTENSET = Flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a SPI interrupt
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param intMask : Or'ed value of SPI_INTENCLR_* values to disable
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_DisableInts(LPC_SPI_T *pSPI, uint32_t Flag)
|
||||
{
|
||||
pSPI->INTENCLR = Flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return enabled SPI interrupts
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return An Or'ed value of SPI_INTENSET_* values
|
||||
* @note Mask the return value with a SPI_INTENSET_* value to determine
|
||||
* if the interrupt is enabled.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_SPI_GetEnabledInts(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return pSPI->INTENSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return pending SPI interrupts
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return An Or'ed value of SPI_INTSTAT_* values
|
||||
* @note Mask the return value with a SPI_INTSTAT_* value to determine
|
||||
* if the interrupt is pending.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_SPI_GetPendingInts(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return pSPI->INTSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flush FIFOs
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPI_FlushFifos(LPC_SPI_T *pSPI);
|
||||
|
||||
/**
|
||||
* @brief Read raw data from receive FIFO with status bits
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Current value in receive data FIFO plus status bits
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_SPI_ReadRawRXFifo(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return pSPI->RXDAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from receive FIFO masking off status bits
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Current value in receive data FIFO
|
||||
* @note The return value is masked with 0xFFFF to not exceed 16-bits. All
|
||||
* other status bits are thrown away. This register should only be read if it
|
||||
* has data in it. This function is useful for systems that don't need SPI
|
||||
* select (SSEL) monitoring.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_SPI_ReadRXData(LPC_SPI_T *pSPI)
|
||||
{
|
||||
return (pSPI->RXDAT & 0xFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to transmit FIFO
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param data : Data to write
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_WriteTXData(LPC_SPI_T *pSPI, uint16_t data)
|
||||
{
|
||||
pSPI->TXDAT = (uint32_t) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SPI TXCTRL register control options
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param bits : TXCTRL register bits to set, amd OR'ed value of SPI_TXDATCTL_* definitions
|
||||
* @return Nothing
|
||||
* @note This function safely sets only the selected bits in the SPI TXCTRL register.
|
||||
* It can be used to enable multiple bits at once.
|
||||
*/
|
||||
void Chip_SPI_SetTXCTRLRegBits(LPC_SPI_T *pSPI, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Clear SPI TXCTRL register control options
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param bits : TXCTRL register bits to clear, amd OR'ed value of SPI_TXDATCTL_* definitions
|
||||
* @return Nothing
|
||||
* @note This function safely clears only the selected bits in the SPI TXCTRL register.
|
||||
* It can be used to disable multiple bits at once.
|
||||
*/
|
||||
void Chip_SPI_ClearTXCTRLRegBits(LPC_SPI_T *pSPI, uint32_t bits);
|
||||
|
||||
/**
|
||||
* @brief Set TX control options (safe)
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param ctrlBits : Or'ed control bits to set
|
||||
* @return Nothing
|
||||
* @note Selectable control states include SPI_TXCTL_DEASSERTNUM_SSEL(0/1/2/3),
|
||||
* SPI_TXCTL_EOT, SPI_TXCTL_EOF, SPI_TXCTL_RXIGNORE, and SPI_TXCTL_FLEN(bits).
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetTXCtl(LPC_SPI_T *pSPI, uint32_t ctrlBits)
|
||||
{
|
||||
Chip_SPI_SetTXCTRLRegBits(pSPI, ctrlBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear TX control options (safe)
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param ctrlBits : Or'ed control bits to clear
|
||||
* @return Nothing
|
||||
* @note Selectable control states include SPI_TXCTL_DEASSERTNUM_SSEL(0/1/2/3),
|
||||
* SPI_TXCTL_EOT, SPI_TXCTL_EOF, SPI_TXCTL_RXIGNORE, and SPI_TXCTL_FLEN(bits).
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_ClearTXCtl(LPC_SPI_T *pSPI, uint32_t ctrlBits)
|
||||
{
|
||||
Chip_SPI_ClearTXCTRLRegBits(pSPI, ctrlBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set TX data transfer size in bits
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param numBits : Number of bits to transmit and receive, must be 1 to 16
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPI_SetXferSize(LPC_SPI_T *pSPI, uint32_t ctrlBits)
|
||||
{
|
||||
Chip_SPI_ClearTXCTRLRegBits(pSPI, SPI_TXCTL_FLENMASK);
|
||||
Chip_SPI_SetTXCTRLRegBits(pSPI, SPI_TXCTL_FLEN(ctrlBits));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SPI_COMMON_540XX_H_ */
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI master driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
static volatile bool xmitOn;
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Get SPI master bit rate */
|
||||
uint32_t Chip_SPIM_GetClockRate(LPC_SPI_T *pSPI)
|
||||
{
|
||||
// Magicoe return Chip_Clock_GetAsyncSysconClockRate() / (pSPI->DIV + 1);
|
||||
return Chip_Clock_GetAsyncSyscon_ClockRate() / (pSPI->DIV + 1);
|
||||
}
|
||||
|
||||
/* Set SPI master bit rate */
|
||||
uint32_t Chip_SPIM_SetClockRate(LPC_SPI_T *pSPI, uint32_t rate)
|
||||
{
|
||||
uint32_t baseClock, div;
|
||||
|
||||
/* Get peripheral base clock rate */
|
||||
// Magicoe baseClock = Chip_Clock_GetAsyncSysconClockRate();
|
||||
baseClock = Chip_Clock_GetAsyncSyscon_ClockRate();
|
||||
/* Compute divider */
|
||||
div = baseClock / rate;
|
||||
|
||||
/* Limit values */
|
||||
if (div == 0) {
|
||||
div = 1;
|
||||
}
|
||||
else if (div > 0x10000) {
|
||||
div = 0x10000;
|
||||
}
|
||||
pSPI->DIV = div - 1;
|
||||
|
||||
return Chip_SPIM_GetClockRate(pSPI);
|
||||
}
|
||||
|
||||
/* Configure SPI Delay parameters */
|
||||
void Chip_SPIM_DelayConfig(LPC_SPI_T *pSPI, SPIM_DELAY_CONFIG_T *pConfig)
|
||||
{
|
||||
pSPI->DLY = (SPI_DLY_PRE_DELAY(pConfig->PreDelay) |
|
||||
SPI_DLY_POST_DELAY(pConfig->PostDelay) |
|
||||
SPI_DLY_FRAME_DELAY(pConfig->FrameDelay) |
|
||||
SPI_DLY_TRANSFER_DELAY(pConfig->TransferDelay - 1));
|
||||
}
|
||||
|
||||
/* Assert a SPI select */
|
||||
void Chip_SPIM_AssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
|
||||
|
||||
/* Assert a SSEL line by driving it low */
|
||||
reg &= ~SPI_TXDATCTL_DEASSERTNUM_SSEL(sselNum);
|
||||
|
||||
pSPI->TXCTRL = reg;
|
||||
}
|
||||
|
||||
/* Deassert a SPI select */
|
||||
void Chip_SPIM_DeAssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = pSPI->TXCTRL & SPI_TXDATCTL_CTRLMASK;
|
||||
pSPI->TXCTRL = reg | SPI_TXDATCTL_DEASSERTNUM_SSEL(sselNum);
|
||||
}
|
||||
|
||||
/* SPI master transfer state change handler */
|
||||
void Chip_SPIM_XferHandler(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
|
||||
{
|
||||
uint32_t data;
|
||||
uint8_t flen;
|
||||
|
||||
/* Get length of a receive value */
|
||||
flen = (pSPI->TXCTRL >> 24) & 0xF;
|
||||
|
||||
/* Master asserts slave */
|
||||
if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSA) != 0) {
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSA);
|
||||
|
||||
/* SSEL assertion callback */
|
||||
xfer->pCB->masterXferCSAssert(xfer);
|
||||
}
|
||||
|
||||
/* Slave de-assertion */
|
||||
if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD) != 0) {
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSD);
|
||||
|
||||
/* If transmitter disabled and deassert happens, the transfer is done */
|
||||
if (xmitOn == false) {
|
||||
xfer->pCB->mMasterXferDone(xfer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit data? */
|
||||
while (((Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY) != 0) && (xmitOn == true)) {
|
||||
if ((xfer->txCount == 1) && (xfer->terminate)) {
|
||||
/* Transfer is done, this will be last data */
|
||||
Chip_SPIM_ForceEndOfTransfer(pSPI);
|
||||
xmitOn = false;
|
||||
}
|
||||
else if (xfer->txCount == 0) {
|
||||
/* Request a new buffer first */
|
||||
xfer->pCB->masterXferSend(xfer);
|
||||
}
|
||||
|
||||
if (xfer->txCount > 0) {
|
||||
/* Send 0 if ignoring transmit */
|
||||
if (xfer->pTXData8 == NULL) {
|
||||
data = 0;
|
||||
}
|
||||
else {
|
||||
/* Copy buffer to data */
|
||||
if (flen > 8) {
|
||||
data = (uint32_t) *xfer->pTXData16;
|
||||
xfer->pTXData16++;
|
||||
}
|
||||
else {
|
||||
data = (uint32_t) *xfer->pTXData8;
|
||||
xfer->pTXData8++;
|
||||
}
|
||||
|
||||
xfer->dataTXferred++;
|
||||
}
|
||||
|
||||
Chip_SPI_WriteTXData(pSPI, data);
|
||||
xfer->txCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data received? */
|
||||
while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY) != 0) {
|
||||
/* Get raw data and status */
|
||||
data = Chip_SPI_ReadRawRXFifo(pSPI);
|
||||
|
||||
/* Only copy data when not ignoring receive */
|
||||
if (xfer->pRXData8 != NULL) {
|
||||
/* Enough size in current buffers? */
|
||||
if (xfer->rxCount == 0) {
|
||||
/* Request a new buffer first */
|
||||
xfer->pCB->masterXferRecv(xfer);
|
||||
}
|
||||
|
||||
/* Copy data to buffer */
|
||||
if (xfer->rxCount > 0) {
|
||||
if (flen > 8) {
|
||||
*xfer->pRXData16 = (uint16_t) (data & 0xFFFF);
|
||||
xfer->pRXData16++;
|
||||
}
|
||||
else {
|
||||
*xfer->pRXData8 = (uint8_t) (data & 0xFF);
|
||||
xfer->pRXData8++;
|
||||
}
|
||||
|
||||
xfer->dataRXferred++;
|
||||
xfer->rxCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start non-blocking SPI master transfer */
|
||||
void Chip_SPIM_Xfer(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
|
||||
{
|
||||
/* Setup SPI master select, data length, EOT/EOF timing, and RX data ignore */
|
||||
pSPI->TXCTRL = xfer->options | SPI_TXDATCTL_DEASSERT_ALL;
|
||||
Chip_SPIM_AssertSSEL(pSPI, xfer->sselNum);
|
||||
|
||||
/* Clear initial transfer states */
|
||||
xfer->dataRXferred = xfer->dataTXferred = 0;
|
||||
|
||||
/* Call main handler to start transfer */
|
||||
xmitOn = true;
|
||||
Chip_SPIM_XferHandler(pSPI, xfer);
|
||||
}
|
||||
|
||||
/* Perform blocking SPI master transfer */
|
||||
void Chip_SPIM_XferBlocking(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer)
|
||||
{
|
||||
/* Start trasnfer */
|
||||
Chip_SPIM_Xfer(pSPI, xfer);
|
||||
|
||||
/* Wait for termination */
|
||||
while (xmitOn == true) {
|
||||
Chip_SPIM_XferHandler(pSPI, xfer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI master driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __SPIM_540XX_H_
|
||||
#define __SPIM_540XX_H_
|
||||
|
||||
#include "spi_common_540xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup SPI_MASTER_540XX CHIP: LPC540XX SPI master driver
|
||||
* @ingroup SPI_COMMON_540XX
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get SPI master bit rate
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return The actual SPI clock bit rate
|
||||
*/
|
||||
uint32_t Chip_SPIM_GetClockRate(LPC_SPI_T *pSPI);
|
||||
|
||||
/**
|
||||
* @brief Set SPI master bit rate
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param rate : Desired clock bit rate for the SPI interface
|
||||
* @return The actual SPI clock bit rate
|
||||
* @note This function will set the SPI clock divider to get closest
|
||||
* to the desired rate as possible.
|
||||
*/
|
||||
uint32_t Chip_SPIM_SetClockRate(LPC_SPI_T *pSPI, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief SPI Delay Configure Struct
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t PreDelay; /** Pre-delay value in SPI clocks, 0 - 15 */
|
||||
uint8_t PostDelay; /** Post-delay value in SPI clocks, 0 - 15 */
|
||||
uint8_t FrameDelay; /** Delay value between frames of a transfer in SPI clocks, 0 - 15 */
|
||||
uint8_t TransferDelay; /** Delay value between transfers in SPI clocks, 1 - 16 */
|
||||
} SPIM_DELAY_CONFIG_T;
|
||||
|
||||
/**
|
||||
* @brief Config SPI Delay parameters
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param pConfig : SPI Delay Configure Struct
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPIM_DelayConfig(LPC_SPI_T *pSPI, SPIM_DELAY_CONFIG_T *pConfig);
|
||||
|
||||
/**
|
||||
* @brief Forces an end of transfer for the current master transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note Use this function to perform an immediate end of trasnfer for the
|
||||
* current master operation. If the master is currently transferring data started
|
||||
* with the Chip_SPIM_Xfer function, this terminates the transfer after the
|
||||
* current byte completes and completes the transfer.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPIM_ForceEndOfTransfer(LPC_SPI_T *pSPI)
|
||||
{
|
||||
pSPI->STAT = SPI_STAT_EOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assert a SPI select
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param sselNum : SPI select to assert, 0 - 3
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPIM_AssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum);
|
||||
|
||||
/**
|
||||
* @brief Deassert a SPI select
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param sselNum : SPI select to deassert, 0 - 3
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_SPIM_DeAssertSSEL(LPC_SPI_T *pSPI, uint8_t sselNum);
|
||||
|
||||
/**
|
||||
* @brief Enable loopback mode
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
* @note Serial input is taken from the serial output (MOSI or MISO) rather
|
||||
* than the serial input pin.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPIM_EnableLoopBack(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_SetCFGRegBits(pSPI, SPI_CFG_LBM_EN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable loopback mode
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_SPIM_DisableLoopBack(LPC_SPI_T *pSPI)
|
||||
{
|
||||
Chip_SPI_ClearCFGRegBits(pSPI, SPI_CFG_LBM_EN);
|
||||
}
|
||||
|
||||
struct SPIM_XFER;
|
||||
|
||||
/** @brief SPI master select assert callback
|
||||
* This callback is called from the SPI master handler when the SPI master
|
||||
* selects the slave (asserts SSEL).
|
||||
*/
|
||||
typedef void (*SPIMasterXferCSAssert)(struct SPIM_XFER *pMasterXfer);
|
||||
|
||||
/** @brief SPI master send data callback
|
||||
* This callback is called from the SPI master handler when the SPI master
|
||||
* needs a data buffer to send.
|
||||
*/
|
||||
typedef void (*SPIMasterXferSend)(struct SPIM_XFER *pMasterXfer);
|
||||
|
||||
/** @brief SPI master receive data callback
|
||||
* This callback is called from the SPI master handler when the SPI master
|
||||
* needs a buffer to place data into.
|
||||
*/
|
||||
typedef void (*SPIMasterXferRecv)(struct SPIM_XFER *pMasterXfer);
|
||||
|
||||
/** @brief SPI master transfer select deassert data callback
|
||||
* This callback is called from the SPI master handler when the SPI master
|
||||
* deasserts the slave select.
|
||||
*/
|
||||
typedef void (*SPIMMasterXferCSDeAssert)(struct SPIM_XFER *pMasterXfer);
|
||||
|
||||
/** @brief SPI master transfer done data callback
|
||||
* This callback is called from the SPI master handler when the SPI master
|
||||
* has completed the transfer and becomes idle.
|
||||
*/
|
||||
typedef void (*SPIMMasterXferDone)(struct SPIM_XFER *pMasterXfer);
|
||||
|
||||
/** SPI slave callback functions */
|
||||
typedef struct {
|
||||
SPIMasterXferCSAssert masterXferCSAssert; /** SPI transfer CS assert, called when a slave select is asserted */
|
||||
SPIMasterXferSend masterXferSend; /** SPI transfer data receive buffer callback, called when a send buffer is needed */
|
||||
SPIMasterXferRecv masterXferRecv; /** SPI transfer send buffer callback, called when send buffer is needed (and SPI_TXCTL_RXIGNORE option is not set) */
|
||||
SPIMMasterXferCSDeAssert mMasterXferCSDeAssert; /** SPI transfer CS deassert, called when a slave select is deasserted */
|
||||
SPIMMasterXferDone mMasterXferDone; /** SPI transfer done callback, called when transfer is complete */
|
||||
} SPIM_CALLBACKS_T;
|
||||
|
||||
/** Slave transfer data context */
|
||||
typedef struct SPIM_XFER {
|
||||
const SPIM_CALLBACKS_T *pCB; /** Pointer to SPI master data callback functions */
|
||||
union { /** Pointer to receive buffer, set to NULL to toss receeive data */
|
||||
uint8_t *pRXData8; /** Receive buffer used with data transfer size <= 8-bits, modified by driver */
|
||||
uint16_t *pRXData16; /** Receive buffer used with data transfer size > 8-bits, modified by driver */
|
||||
};
|
||||
|
||||
union { /** Pointer to transmit buffer, set to NULL to transmit 0x0 */
|
||||
uint8_t *pTXData8; /** Send buffer used with data transfer size <= 8-bits, modified by driver */
|
||||
uint16_t *pTXData16; /** Send buffer used with data transfer size > 8-bits, modified by driver */
|
||||
};
|
||||
|
||||
uint32_t options; /** Master transfer options, an OR'ed value of SPI_TXCTL_EOT, SPI_TXCTL_EOF, SPI_TXCTL_RXIGNORE, and SPI_TXCTL_FLEN(bits) */
|
||||
uint16_t rxCount; /** Size of the pRXData buffer in items (not bytes), modified by driver */
|
||||
uint16_t txCount; /** Number of items (not bytes) to send in pTXData buffer, modified by driver */
|
||||
uint16_t dataRXferred; /** Total items (not bytes) received, modified by driver */
|
||||
uint16_t dataTXferred; /** Total items (not bytes) transmitted, modified by driver */
|
||||
uint8_t sselNum; /** Slave number assigned to this transfer, 0 - 3, used by driver to select slave */
|
||||
bool terminate; /** Transfer will terminate when txCount goes to 0 and master goes idle, must be set before last byte is sent */
|
||||
} SPIM_XFER_T;
|
||||
|
||||
/**
|
||||
* @brief SPI master transfer state change handler
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIM_XFER_T structure see notes below
|
||||
* @return Nothing
|
||||
* @note See @ref SPIM_XFER_T for more information on this function. When using
|
||||
* this function, the SPI master interrupts should be enabled and setup in the SPI
|
||||
* interrupt handler to call this function when they fire. This function is meant
|
||||
* to be called from the interrupt handler.
|
||||
*/
|
||||
void Chip_SPIM_XferHandler(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @brief Start non-blocking SPI master transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIM_XFER_T structure see notes below
|
||||
* @return Nothing
|
||||
* @note This function starts a non-blocking SPI master transfer with the
|
||||
* parameters setup in the passed @ref SPIM_XFER_T structure. Once the transfer is
|
||||
* started, the interrupt handler must call Chip_SPIM_XferHandler to keep the
|
||||
* transfer going and fed with data. This function should only be called when
|
||||
* the master is idle.<br>
|
||||
*
|
||||
* This function must be called with the options and sselNum fields correctly
|
||||
* setup. Initial data buffers and the callback pointer must also be setup. No
|
||||
* sanity checks are performed on the passed data.<br>
|
||||
*
|
||||
* Example call:<br>
|
||||
* SPIM_XFER_T mxfer;
|
||||
* mxfer.pCB = &masterCallbacks;
|
||||
* mxfer.sselNum = 2; // Use chip select 2
|
||||
* mxfer.options = SPI_TXCTL_FLEN(8); // 8 data bits, supports 1 - 16 bits
|
||||
* mxfer.options |= SPI_TXCTL_EOT | SPI_TXCTL_EOF; // Apply frame and transfer delays to master transfer
|
||||
* mxfer.options |= SPI_TXCTL_RXIGNORE; // Ignore RX data, will toss receive data regardless of pRXData8 or pRXData16 buffer
|
||||
* mxfer.pTXData8 = SendBuffer;
|
||||
* mxfer.txCount = 16; // Number of bytes to send before SPIMasterXferSend callback is called
|
||||
* mxfer.pRXData8 = RecvBuffer; // Will not receive data if pRXData8/pRXData16 is NULL or SPI_TXCTL_RXIGNORE option is set
|
||||
* mxfer.rxCount = 16; // Number of bytes to receive before SPIMasterXferRecv callback is called
|
||||
* Chip_SPIM_Xfer(LPC_SPI0, &mxfer); // Start transfer
|
||||
*
|
||||
* Note that the transfer, once started, needs to be constantly fed by the callbacks.
|
||||
* The txCount and rxCount field only indicate the buffer size before the callbacks are called.
|
||||
* To terminate the transfer, the SPIMasterXferSend callback must set the terminate field.
|
||||
*/
|
||||
void Chip_SPIM_Xfer(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @brief Perform blocking SPI master transfer
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIM_XFER_T structure see notes below
|
||||
* @return Nothing
|
||||
* @note This function starts a blocking SPI master transfer with the
|
||||
* parameters setup in the passed @ref SPIM_XFER_T structure. Once the transfer is
|
||||
* started, the callbacks in Chip_SPIM_XferHandler may be called to keep the
|
||||
* transfer going and fed with data. SPI interrupts must be disabled prior to
|
||||
* calling this function. It is not recommended to use this function.<br>
|
||||
*/
|
||||
void Chip_SPIM_XferBlocking(LPC_SPI_T *pSPI, SPIM_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SPIM_540XX_H_ */
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI master driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/* Flag used to tell polling function (if used) that a deassert event
|
||||
happened */
|
||||
static volatile bool deasserted;
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Determine SSEL associated with the current data value */
|
||||
static uint8_t Chip_SPIS_FindSSEL(LPC_SPI_T *pSPI, uint32_t data)
|
||||
{
|
||||
int i;
|
||||
uint8_t ssel = 0;
|
||||
|
||||
for (i = 0; i <= 3; i++) {
|
||||
if ((data & SPI_RXDAT_RXSSELNUM_INACTIVE(i)) == 0) {
|
||||
/* Signal is active on low */
|
||||
ssel = (uint8_t) i;
|
||||
}
|
||||
}
|
||||
|
||||
return ssel;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* SPI slave transfer state change handler */
|
||||
uint32_t Chip_SPIS_XferHandler(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer)
|
||||
{
|
||||
uint32_t staterr, data;
|
||||
uint8_t flen;
|
||||
|
||||
/* Get length of a receive value */
|
||||
flen = (pSPI->TXCTRL >> 24) & 0xF;
|
||||
|
||||
/* Get errors for later, we'll continue even if errors occur, but we notify
|
||||
caller on return */
|
||||
staterr = Chip_SPI_GetStatus(pSPI) & (SPI_STAT_RXOV | SPI_STAT_TXUR);
|
||||
if (staterr != 0) {
|
||||
Chip_SPI_ClearStatus(pSPI, staterr);
|
||||
}
|
||||
|
||||
/* Slave assertion */
|
||||
if ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSA) != 0) {
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSA);
|
||||
|
||||
/* Determine SPI select. Read the data FIFO to get the slave number. Data
|
||||
should not be in the receive FIFO yet, only the statuses */
|
||||
xfer->sselNum = Chip_SPIS_FindSSEL(pSPI, Chip_SPI_ReadRawRXFifo(pSPI));
|
||||
|
||||
/* SSEL assertion callback */
|
||||
xfer->pCB->slaveXferCSAssert(xfer);
|
||||
}
|
||||
|
||||
/* Transmit data? */
|
||||
while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_TXRDY) != 0) {
|
||||
if (xfer->txCount == 0) {
|
||||
/* Request a new buffer first */
|
||||
xfer->pCB->slaveXferSend(xfer);
|
||||
}
|
||||
|
||||
/* Send 0 on empty buffer or count */
|
||||
if ((xfer->txCount == 0) || (xfer->pTXData8 == NULL)) {
|
||||
data = 0;
|
||||
}
|
||||
else {
|
||||
/* Copy buffer to data */
|
||||
if (flen > 8) {
|
||||
data = (uint32_t) *xfer->pTXData16;
|
||||
xfer->pTXData16++;
|
||||
}
|
||||
else {
|
||||
data = (uint32_t) *xfer->pTXData8;
|
||||
xfer->pTXData8++;
|
||||
}
|
||||
|
||||
xfer->dataTXferred++;
|
||||
xfer->txCount--;
|
||||
}
|
||||
|
||||
Chip_SPI_WriteTXData(pSPI, data);
|
||||
}
|
||||
|
||||
/* Data received? */
|
||||
while ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY) != 0) {
|
||||
/* Get raw data and status */
|
||||
data = Chip_SPI_ReadRawRXFifo(pSPI);
|
||||
|
||||
/* Only copy data when not ignoring receive */
|
||||
if (xfer->pRXData8 != NULL) {
|
||||
/* Enough size in current buffers? */
|
||||
if (xfer->rxCount == 0) {
|
||||
/* Request a new buffer first */
|
||||
xfer->pCB->slaveXferRecv(xfer);
|
||||
}
|
||||
|
||||
/* Copy data to buffer */
|
||||
if (flen > 8) {
|
||||
*xfer->pRXData16 = (uint16_t) (data & 0xFFFF);
|
||||
xfer->pRXData16++;
|
||||
}
|
||||
else {
|
||||
*xfer->pRXData8 = (uint8_t) (data & 0xFF);
|
||||
xfer->pRXData8++;
|
||||
}
|
||||
|
||||
xfer->dataRXferred++;
|
||||
xfer->rxCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Slave de-assertion */
|
||||
if (((Chip_SPI_GetStatus(pSPI) & SPI_STAT_SSD) != 0) && ((Chip_SPI_GetStatus(pSPI) & SPI_STAT_RXRDY) == 0)) {
|
||||
Chip_SPI_ClearStatus(pSPI, SPI_STAT_SSD);
|
||||
xfer->pCB->slaveXferCSDeAssert(xfer);
|
||||
deasserted = true;
|
||||
}
|
||||
|
||||
return staterr;
|
||||
}
|
||||
|
||||
/* SPI slave transfer blocking function */
|
||||
uint32_t Chip_SPIS_XferBlocking(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
/* Wait forever until deassertion event */
|
||||
deasserted = false;
|
||||
while ((!deasserted) && (status == 0)) {
|
||||
status = Chip_SPIS_XferHandler(pSPI, xfer);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* @brief LPC540XX SPI slave driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2014
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __SPIS_540XX_H_
|
||||
#define __SPIS_540XX_H_
|
||||
|
||||
#include "spi_common_540xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup SPI_SLAVE_540XX CHIP: LPC540XX SPI slave driver
|
||||
* @ingroup SPI_COMMON_540XX
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct SPIS_XFER;
|
||||
|
||||
/** @brief SPI slave select assertion callback
|
||||
* This callback is called from the SPI slave handler when an SPI slave select (SSEL)
|
||||
* is initially asserted. It is used to indicate the start of a slave transfer that
|
||||
* will happen on the bus.
|
||||
*/
|
||||
typedef void (*SPISlaveXferCSAssert)(struct SPIS_XFER *pSlaveXfer);
|
||||
|
||||
/** @brief SPI slave send data callback
|
||||
* This callback is called from the SPI slave handler when an SPI slave select (SSEL)
|
||||
* needs a data buffer to send.
|
||||
*/
|
||||
typedef void (*SPISlaveXferSend)(struct SPIS_XFER *pSlaveXfer);
|
||||
|
||||
/** @brief SPI slave receive data callback
|
||||
* This callback is called from the SPI slave handler when an SPI slave select (SSEL)
|
||||
* needs a buffer to place data.
|
||||
*/
|
||||
typedef void (*SPISlaveXferRecv)(struct SPIS_XFER *pSlaveXfer);
|
||||
|
||||
/** @brief SPI slave select de-assertion callback
|
||||
* This callback is called from the SPI slave handler when an SPI slave select (SSEL)
|
||||
* is de-asserted. It can be used to indicate the end of a transfer.
|
||||
*/
|
||||
typedef void (*SPISlaveXferCSDeAssert)(struct SPIS_XFER *pSlaveXfer);
|
||||
|
||||
/** SPI slave callback functions */
|
||||
typedef struct {
|
||||
SPISlaveXferCSAssert slaveXferCSAssert; /** SPI transfer start callback, called on SPI CS assertion */
|
||||
SPISlaveXferSend slaveXferSend; /** SPI transfer data receive buffer callback, called when a receive buffer is needed */
|
||||
SPISlaveXferRecv slaveXferRecv; /** SPI transfer send buffer callback, called when data is needed */
|
||||
SPISlaveXferCSDeAssert slaveXferCSDeAssert; /** SPI transfer completion callback, called on SPI CS deassertion */
|
||||
} SPIS_CALLBACKS_T;
|
||||
|
||||
/** Slave transfer data context */
|
||||
typedef struct SPIS_XFER {
|
||||
const SPIS_CALLBACKS_T *pCB; /** Pointer to SPI slave callback functions */
|
||||
union { /** Pointer to receive buffer, set to NULL to toss receeive data */
|
||||
uint8_t *pRXData8; /** Receive buffer used with data transfer size <= 8-bits, modified by driver */
|
||||
uint16_t *pRXData16; /** Receive buffer used with data transfer size > 8-bits, modified by driver */
|
||||
};
|
||||
|
||||
union { /** Pointer to transmit buffer, set to NULL to transmit 0x0 */
|
||||
uint8_t *pTXData8; /** Send buffer used with data transfer size <= 8-bits, modified by driver */
|
||||
uint16_t *pTXData16; /** Send buffer used with data transfer size > 8-bits, modified by driver */
|
||||
};
|
||||
|
||||
uint16_t rxCount; /** Size of the pRXData buffer in items (not bytes), modified by driver */
|
||||
uint16_t txCount; /** Number of items (not bytes) to send in pTXData buffer, modified by driver */
|
||||
uint16_t dataRXferred; /** Total items (not bytes) received, modified by driver */
|
||||
uint16_t dataTXferred; /** Total items (not bytes) transmitted, modified by driver */
|
||||
uint8_t sselNum; /** Slave number assigned to this transfer, 0 - 3, modified by driver */
|
||||
} SPIS_XFER_T;
|
||||
|
||||
/**
|
||||
* @brief SPI slave transfer state change handler
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIS_XFER_T structure see notes below
|
||||
* @return returns 0 on success, or SPI_STAT_RXOV and/or SPI_STAT_TXUR on an error
|
||||
* @note See @ref SPIS_XFER_T for more information on this function. When using
|
||||
* this function, the SPI slave interrupts should be enabled and setup in the SPI
|
||||
* interrupt handler to call this function when they fire. This function is meant
|
||||
* to be called from the interrupt handler. The @ref SPIS_XFER_T data does not need
|
||||
* to be setup prior to the call and should be setup by the callbacks instead.<br>
|
||||
*
|
||||
* The callbacks are handled in the interrupt handler. If you are getting overflow
|
||||
* or underflow errors, you might need to lower the speed of the master clock or
|
||||
* extend the master's select assetion time.<br>
|
||||
*/
|
||||
uint32_t Chip_SPIS_XferHandler(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @brief Pre-buffers slave transmit data
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIS_XFER_T structure see notes below
|
||||
* @return Nothing
|
||||
* @note Pre-buffering allows the slave to prime the transmit FIFO with data prior to
|
||||
* the master starting a transfer. If data is not pre-buffered, the initial slave
|
||||
* transmit data will always be 0x0 with a slave transmit underflow status.
|
||||
* Pre-buffering is best used when only a single slave select is used by an
|
||||
* application.
|
||||
*/
|
||||
STATIC INLINE void Chip_SPIS_PreBuffSlave(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer)
|
||||
{
|
||||
Chip_SPIS_XferHandler(pSPI, xfer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI slave transfer blocking function
|
||||
* @param pSPI : The base of SPI peripheral on the chip
|
||||
* @param xfers : Pointer to a SPIS_XFER_T structure
|
||||
* @return returns 0 on success, or SPI_STAT_RXOV and/or SPI_STAT_TXUR on an error
|
||||
* @note This function performs a blocking transfer on the SPI slave interface.
|
||||
* It is not recommended to use this function. Once this function is called, it
|
||||
* will block forever until a slave transfer consisting of a slave SSEL assertion,
|
||||
* and de-assertion occur. The callbacks are still used for slave data buffer
|
||||
* management. SPI interrupts must be disabled prior to calling this function.
|
||||
*/
|
||||
uint32_t Chip_SPIS_XferBlocking(LPC_SPI_T *pSPI, SPIS_XFER_T *xfer);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SPIS_540XX_H_ */
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* @brief LPC540XX UART driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licenser disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Private types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Public types/enumerations/variables
|
||||
****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Private functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Return UART clock ID from the UART register address */
|
||||
static CHIP_SYSCON_CLOCK_T getUARTClockID(LPC_USART_T *pUART)
|
||||
{
|
||||
if (pUART == LPC_USART0) {
|
||||
return SYSCON_CLOCK_USART0;
|
||||
}
|
||||
else if (pUART == LPC_USART1) {
|
||||
return SYSCON_CLOCK_USART1;
|
||||
}
|
||||
else if (pUART == LPC_USART2) {
|
||||
return SYSCON_CLOCK_USART2;
|
||||
}
|
||||
return SYSCON_CLOCK_USART3;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Initialize the UART peripheral */
|
||||
void Chip_UART_Init(LPC_USART_T *pUART)
|
||||
{
|
||||
/* Enable USART clock */
|
||||
Chip_Clock_EnablePeriphClock(getUARTClockID(pUART));
|
||||
|
||||
/* UART reset */
|
||||
if (pUART == LPC_USART0) {
|
||||
/* Peripheral reset control to USART0 */
|
||||
Chip_SYSCON_PeriphReset(RESET_USART0);
|
||||
}
|
||||
else if (pUART == LPC_USART1) {
|
||||
/* Peripheral reset control to USART1 */
|
||||
Chip_SYSCON_PeriphReset(RESET_USART1);
|
||||
}
|
||||
else if (pUART == LPC_USART2) {
|
||||
/* Peripheral reset control to USART2 */
|
||||
Chip_SYSCON_PeriphReset(RESET_USART2);
|
||||
}
|
||||
else if (pUART == LPC_USART3) {
|
||||
/* Peripheral reset control to USART3 */
|
||||
Chip_SYSCON_PeriphReset(RESET_USART3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the UART peripheral */
|
||||
void Chip_UART_DeInit(LPC_USART_T *pUART)
|
||||
{
|
||||
/* Enable USART clock */
|
||||
Chip_Clock_DisablePeriphClock(getUARTClockID(pUART));
|
||||
}
|
||||
|
||||
/* Transmit a byte array through the UART peripheral (non-blocking) */
|
||||
int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes)
|
||||
{
|
||||
int sent = 0;
|
||||
uint8_t *p8 = (uint8_t *) data;
|
||||
|
||||
/* Send until the transmit FIFO is full or out of bytes */
|
||||
while ((sent < numBytes) &&
|
||||
((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0)) {
|
||||
Chip_UART_SendByte(pUART, *p8);
|
||||
p8++;
|
||||
sent++;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/* Transmit a byte array through the UART peripheral (blocking) */
|
||||
int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes)
|
||||
{
|
||||
int pass, sent = 0;
|
||||
uint8_t *p8 = (uint8_t *) data;
|
||||
|
||||
while (numBytes > 0) {
|
||||
pass = Chip_UART_Send(pUART, p8, numBytes);
|
||||
numBytes -= pass;
|
||||
sent += pass;
|
||||
p8 += pass;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/* Read data through the UART peripheral (non-blocking) */
|
||||
int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes)
|
||||
{
|
||||
int readBytes = 0;
|
||||
uint8_t *p8 = (uint8_t *) data;
|
||||
|
||||
/* Send until the transmit FIFO is full or out of bytes */
|
||||
while ((readBytes < numBytes) &&
|
||||
((Chip_UART_GetStatus(pUART) & UART_STAT_RXRDY) != 0)) {
|
||||
*p8 = Chip_UART_ReadByte(pUART);
|
||||
p8++;
|
||||
readBytes++;
|
||||
}
|
||||
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
/* Read data through the UART peripheral (blocking) */
|
||||
int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes)
|
||||
{
|
||||
int pass, readBytes = 0;
|
||||
uint8_t *p8 = (uint8_t *) data;
|
||||
|
||||
while (readBytes < numBytes) {
|
||||
pass = Chip_UART_Read(pUART, p8, numBytes);
|
||||
numBytes -= pass;
|
||||
readBytes += pass;
|
||||
p8 += pass;
|
||||
}
|
||||
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
/* Set baud rate for UART */
|
||||
void Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate)
|
||||
{
|
||||
uint32_t err, uart_fra_multiplier, baudRateGenerator;
|
||||
uint32_t AsyncSysconSystemClock = Chip_Clock_GetAsyncSyscon_ClockRate(); // Magicoe fixed Chip_Clock_GetAsyncSysconClockRate();
|
||||
|
||||
/* Calculate baudrate generator value */
|
||||
baudRateGenerator = AsyncSysconSystemClock / (16 * baudrate);
|
||||
err = AsyncSysconSystemClock - baudRateGenerator * 16 * baudrate;
|
||||
uart_fra_multiplier = (err * 0xFF) / (baudRateGenerator * 16 * baudrate);
|
||||
pUART->BRG = baudRateGenerator - 1; /* baud rate */
|
||||
Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_FRG);
|
||||
Chip_SYSCON_SetUSARTFRGCtrl(uart_fra_multiplier, 0xFF);
|
||||
}
|
||||
|
||||
/* UART receive-only interrupt handler for ring buffers */
|
||||
void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
|
||||
{
|
||||
/* New data will be ignored if data not popped in time */
|
||||
while ((Chip_UART_GetStatus(pUART) & UART_STAT_RXRDY) != 0) {
|
||||
uint8_t ch = Chip_UART_ReadByte(pUART);
|
||||
RingBuffer_Insert(pRB, &ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* UART transmit-only interrupt handler for ring buffers */
|
||||
void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB)
|
||||
{
|
||||
uint8_t ch;
|
||||
|
||||
/* Fill FIFO until full or until TX ring buffer is empty */
|
||||
while (((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0) &&
|
||||
RingBuffer_Pop(pRB, &ch)) {
|
||||
Chip_UART_SendByte(pUART, ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Populate a transmit ring buffer and start UART transmit */
|
||||
uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int count)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint8_t *p8 = (uint8_t *) data;
|
||||
|
||||
/* Don't let UART transmit ring buffer change in the UART IRQ handler */
|
||||
Chip_UART_IntDisable(pUART, UART_INTEN_TXRDY);
|
||||
|
||||
/* Move as much data as possible into transmit ring buffer */
|
||||
ret = RingBuffer_InsertMult(pRB, p8, count);
|
||||
Chip_UART_TXIntHandlerRB(pUART, pRB);
|
||||
|
||||
/* Add additional data to transmit ring buffer if possible */
|
||||
ret += RingBuffer_InsertMult(pRB, (p8 + ret), (count - ret));
|
||||
|
||||
/* Enable UART transmit interrupt */
|
||||
Chip_UART_IntEnable(pUART, UART_INTEN_TXRDY);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Copy data from a receive ring buffer */
|
||||
int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes)
|
||||
{
|
||||
(void) pUART;
|
||||
|
||||
return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes);
|
||||
}
|
||||
|
||||
/* UART receive/transmit interrupt handler for ring buffers */
|
||||
void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB)
|
||||
{
|
||||
/* Handle transmit interrupt if enabled */
|
||||
if ((Chip_UART_GetStatus(pUART) & UART_STAT_TXRDY) != 0) {
|
||||
Chip_UART_TXIntHandlerRB(pUART, pTXRB);
|
||||
|
||||
/* Disable transmit interrupt if the ring buffer is empty */
|
||||
if (RingBuffer_IsEmpty(pTXRB)) {
|
||||
Chip_UART_IntDisable(pUART, UART_INTEN_TXRDY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle receive interrupt */
|
||||
Chip_UART_RXIntHandlerRB(pUART, pRXRB);
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* @brief LPC540XX UART driver
|
||||
*
|
||||
* @note
|
||||
* Copyright(C) NXP Semiconductors, 2012
|
||||
* All rights reserved.
|
||||
*
|
||||
* @par
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* LPC products. This software is supplied "AS IS" without any warranties of
|
||||
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||||
* all warranties, express or implied, including all implied warranties of
|
||||
* merchantability, fitness for a particular purpose and non-infringement of
|
||||
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||||
* or liability for the use of the software, conveys no license or rights under any
|
||||
* patent, copyright, mask work right, or any other intellectual property rights in
|
||||
* or to any products. NXP Semiconductors reserves the right to make changes
|
||||
* in the software without notification. NXP Semiconductors also makes no
|
||||
* representation or warranty that such application will be suitable for the
|
||||
* specified use without further testing or modification.
|
||||
*
|
||||
* @par
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, under NXP Semiconductors' and its
|
||||
* licensor's relevant copyrights in the software, without fee, provided that it
|
||||
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||||
* copyright, permission, and disclaimer notice must appear in all copies of
|
||||
* this code.
|
||||
*/
|
||||
|
||||
#ifndef __UART_540XX_H_
|
||||
#define __UART_540XX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ring_buffer.h"
|
||||
|
||||
/** @defgroup UART_540XX CHIP: LPC540XX UART Driver
|
||||
* @ingroup CHIP_LPC540XX_Drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief UART register block structure
|
||||
*/
|
||||
typedef struct {
|
||||
__IO uint32_t CFG; /*!< Configuration register */
|
||||
__IO uint32_t CTRL; /*!< Control register */
|
||||
__IO uint32_t STAT; /*!< Status register */
|
||||
__IO uint32_t INTENSET; /*!< Interrupt Enable read and set register */
|
||||
__O uint32_t INTENCLR; /*!< Interrupt Enable clear register */
|
||||
__I uint32_t RXDATA; /*!< Receive Data register */
|
||||
__I uint32_t RXDATA_STAT; /*!< Receive Data with status register */
|
||||
__IO uint32_t TXDATA; /*!< Transmit data register */
|
||||
__IO uint32_t BRG; /*!< Baud Rate Generator register */
|
||||
__IO uint32_t INTSTAT; /*!< Interrupt status register */
|
||||
__IO uint32_t OSR; /*!< Oversample selection register */
|
||||
__IO uint32_t ADDR; /*!< Address register */
|
||||
} LPC_USART_T;
|
||||
|
||||
/**
|
||||
* @brief UART CFG register definitions
|
||||
*/
|
||||
#define UART_CFG_ENABLE (0x01 << 0)
|
||||
#define UART_CFG_DATALEN_7 (0x00 << 2) /*!< UART 7 bit length mode */
|
||||
#define UART_CFG_DATALEN_8 (0x01 << 2) /*!< UART 8 bit length mode */
|
||||
#define UART_CFG_DATALEN_9 (0x02 << 2) /*!< UART 9 bit length mode */
|
||||
#define UART_CFG_PARITY_NONE (0x00 << 4) /*!< No parity */
|
||||
#define UART_CFG_PARITY_EVEN (0x02 << 4) /*!< Even parity */
|
||||
#define UART_CFG_PARITY_ODD (0x03 << 4) /*!< Odd parity */
|
||||
#define UART_CFG_STOPLEN_1 (0x00 << 6) /*!< UART One Stop Bit Select */
|
||||
#define UART_CFG_STOPLEN_2 (0x01 << 6) /*!< UART Two Stop Bits Select */
|
||||
#define UART_CFG_MODE32K (0x01 << 7) /*!< UART 32K MODE */
|
||||
#define UART_CFG_LINMODE (0x01 << 8) /*!< UART LIN MODE */
|
||||
#define UART_CFG_CTSEN (0x01 << 9) /*!< CTS enable bit */
|
||||
#define UART_CFG_SYNCEN (0x01 << 11) /*!< Synchronous mode enable bit */
|
||||
#define UART_CFG_CLKPOL (0x01 << 12) /*!< Un_RXD rising edge sample enable bit */
|
||||
#define UART_CFG_SYNCMST (0x01 << 14) /*!< Select master mode (synchronous mode) enable bit */
|
||||
#define UART_CFG_LOOP (0x01 << 15) /*!< Loopback mode enable bit */
|
||||
|
||||
/**
|
||||
* @brief UART CTRL register definitions
|
||||
*/
|
||||
#define UART_CTRL_TXBRKEN (0x01 << 1) /*!< Continuous break enable bit */
|
||||
#define UART_CTRL_ADDRDET (0x01 << 2) /*!< Address detect mode enable bit */
|
||||
#define UART_CTRL_TXDIS (0x01 << 6) /*!< Transmit disable bit */
|
||||
#define UART_CTRL_CC (0x01 << 8) /*!< Continuous Clock mode enable bit */
|
||||
#define UART_CTRL_CLRCC (0x01 << 9) /*!< Clear Continuous Clock bit */
|
||||
#define UART_CTRL_AUTOBAUD (0x01 << 16) /*!< Auto baud bit */
|
||||
|
||||
/**
|
||||
* @brief UART STAT register definitions
|
||||
*/
|
||||
#define UART_STAT_RXRDY (0x01 << 0) /*!< Receiver ready */
|
||||
#define UART_STAT_RXIDLE (0x01 << 1) /*!< Receiver idle */
|
||||
#define UART_STAT_TXRDY (0x01 << 2) /*!< Transmitter ready for data */
|
||||
#define UART_STAT_TXIDLE (0x01 << 3) /*!< Transmitter idle */
|
||||
#define UART_STAT_CTS (0x01 << 4) /*!< Status of CTS signal */
|
||||
#define UART_STAT_DELTACTS (0x01 << 5) /*!< Change in CTS state */
|
||||
#define UART_STAT_TXDISINT (0x01 << 6) /*!< Transmitter disabled */
|
||||
#define UART_STAT_OVERRUNINT (0x01 << 8) /*!< Overrun Error interrupt flag. */
|
||||
#define UART_STAT_RXBRK (0x01 << 10) /*!< Received break */
|
||||
#define UART_STAT_DELTARXBRK (0x01 << 11) /*!< Change in receive break detection */
|
||||
#define UART_STAT_START (0x01 << 12) /*!< Start detected */
|
||||
#define UART_STAT_FRM_ERRINT (0x01 << 13) /*!< Framing Error interrupt flag */
|
||||
#define UART_STAT_PAR_ERRINT (0x01 << 14) /*!< Parity Error interrupt flag */
|
||||
#define UART_STAT_RXNOISEINT (0x01 << 15) /*!< Received Noise interrupt flag */
|
||||
#define UART_STAT_ABERR (0x01 << 16) /*!< Auto baud error flag */
|
||||
|
||||
/**
|
||||
* @brief UART INTENSET/INTENCLR register definitions
|
||||
*/
|
||||
#define UART_INTEN_RXRDY (0x01 << 0) /*!< Receive Ready interrupt */
|
||||
#define UART_INTEN_TXRDY (0x01 << 2) /*!< Transmit Ready interrupt */
|
||||
#define UART_INTEN_DELTACTS (0x01 << 5) /*!< Change in CTS state interrupt */
|
||||
#define UART_INTEN_TXDIS (0x01 << 6) /*!< Transmitter disable interrupt */
|
||||
#define UART_INTEN_OVERRUN (0x01 << 8) /*!< Overrun error interrupt */
|
||||
#define UART_INTEN_DELTARXBRK (0x01 << 11) /*!< Change in receiver break detection interrupt */
|
||||
#define UART_INTEN_START (0x01 << 12) /*!< Start detect interrupt */
|
||||
#define UART_INTEN_FRAMERR (0x01 << 13) /*!< Frame error interrupt */
|
||||
#define UART_INTEN_PARITYERR (0x01 << 14) /*!< Parity error interrupt */
|
||||
#define UART_INTEN_RXNOISE (0x01 << 15) /*!< Received noise interrupt */
|
||||
|
||||
/**
|
||||
* @brief Enable the UART
|
||||
* @param pUART : Pointer to selected UARTx peripheral
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_Enable(LPC_USART_T *pUART)
|
||||
{
|
||||
pUART->CFG |= UART_CFG_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the UART
|
||||
* @param pUART : Pointer to selected UARTx peripheral
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_Disable(LPC_USART_T *pUART)
|
||||
{
|
||||
pUART->CFG &= ~UART_CFG_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable transmission on UART TxD pin
|
||||
* @param pUART : Pointer to selected pUART peripheral
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_TXEnable(LPC_USART_T *pUART)
|
||||
{
|
||||
pUART->CTRL &= ~UART_CTRL_TXDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable transmission on UART TxD pin
|
||||
* @param pUART : Pointer to selected pUART peripheral
|
||||
* @return Nothing
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_TXDisable(LPC_USART_T *pUART)
|
||||
{
|
||||
pUART->CTRL |= UART_CTRL_TXDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set auto baud
|
||||
* @param pUART : Pointer to selected pUART peripheral
|
||||
* @return true if auto baud succeeds, false if fails
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_UART_AutoBaud(LPC_USART_T *pUART)
|
||||
{
|
||||
while ( (pUART->STAT & UART_STAT_RXIDLE) != UART_STAT_RXIDLE );
|
||||
pUART->CTRL |= UART_CTRL_AUTOBAUD;
|
||||
while ( pUART->CTRL & UART_CTRL_AUTOBAUD ) {
|
||||
if ( pUART->STAT & UART_STAT_ABERR ) {
|
||||
pUART->STAT = UART_STAT_ABERR;
|
||||
return ( false );
|
||||
}
|
||||
}
|
||||
return ( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit a single data byte through the UART peripheral
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param data : Byte to transmit
|
||||
* @return Nothing
|
||||
* @note This function attempts to place a byte into the UART transmit
|
||||
* holding register regard regardless of UART state.
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_SendByte(LPC_USART_T *pUART, uint8_t data)
|
||||
{
|
||||
pUART->TXDATA = (uint32_t) data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a single byte data from the UART peripheral
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @return A single byte of data read
|
||||
* @note This function reads a byte from the UART receive FIFO or
|
||||
* receive hold register regard regardless of UART state. The
|
||||
* FIFO status should be read first prior to using this function
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_UART_ReadByte(LPC_USART_T *pUART)
|
||||
{
|
||||
/* Strip off undefined reserved bits, keep 9 lower bits */
|
||||
return (uint32_t) (pUART->RXDATA & 0x000001FF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable UART interrupts
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param intMask : OR'ed Interrupts to enable
|
||||
* @return Nothing
|
||||
* @note Use an OR'ed value of UART_INTEN_* definitions with this function
|
||||
* to enable specific UART interrupts.
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_IntEnable(LPC_USART_T *pUART, uint32_t intMask)
|
||||
{
|
||||
pUART->INTENSET = intMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable UART interrupts
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param intMask : OR'ed Interrupts to disable
|
||||
* @return Nothing
|
||||
* @note Use an OR'ed value of UART_INTEN_* definitions with this function
|
||||
* to disable specific UART interrupts.
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_IntDisable(LPC_USART_T *pUART, uint32_t intMask)
|
||||
{
|
||||
pUART->INTENCLR = intMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns UART interrupts that are enabled
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @return Returns the enabled UART interrupts
|
||||
* @note Use an OR'ed value of UART_INTEN_* definitions with this function
|
||||
* to determine which interrupts are enabled. You can check
|
||||
* for multiple enabled bits if needed.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_UART_GetIntsEnabled(LPC_USART_T *pUART)
|
||||
{
|
||||
return pUART->INTENSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get UART interrupt status
|
||||
* @param pUART : The base of UART peripheral on the chip
|
||||
* @return The Interrupt status register of UART
|
||||
* @note Multiple interrupts may be pending. Mask the return value
|
||||
* with one or more UART_INTEN_* definitions to determine
|
||||
* pending interrupts.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_UART_GetIntStatus(LPC_USART_T *pUART)
|
||||
{
|
||||
return pUART->INTSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure data width, parity and stop bits
|
||||
* @param pUART : Pointer to selected pUART peripheral
|
||||
* @param config : UART configuration, OR'ed values of select UART_CFG_* defines
|
||||
* @return Nothing
|
||||
* @note Select OR'ed config options for the UART from the UART_CFG_PARITY_*,
|
||||
* UART_CFG_STOPLEN_*, and UART_CFG_DATALEN_* definitions. For example,
|
||||
* a configuration of 8 data bits, 1 stop bit, and even (enabled) parity would be
|
||||
* (UART_CFG_DATALEN_8 | UART_CFG_STOPLEN_1 | UART_CFG_PARITY_EVEN). Will not
|
||||
* alter other bits in the CFG register.
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_ConfigData(LPC_USART_T *pUART, uint32_t config)
|
||||
{
|
||||
pUART->CFG = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART status register
|
||||
* @param pUART : Pointer to selected UARTx peripheral
|
||||
* @return UART status register
|
||||
* @note Multiple statuses may be pending. Mask the return value
|
||||
* with one or more UART_STAT_* definitions to determine
|
||||
* statuses.
|
||||
*/
|
||||
STATIC INLINE uint32_t Chip_UART_GetStatus(LPC_USART_T *pUART)
|
||||
{
|
||||
return pUART->STAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the UART status register
|
||||
* @param pUART : Pointer to selected UARTx peripheral
|
||||
* @param stsMask : OR'ed statuses to disable
|
||||
* @return Nothing
|
||||
* @note Multiple interrupts may be pending. Mask the return value
|
||||
* with one or more UART_INTEN_* definitions to determine
|
||||
* pending interrupts.
|
||||
*/
|
||||
STATIC INLINE void Chip_UART_ClearStatus(LPC_USART_T *pUART, uint32_t stsMask)
|
||||
{
|
||||
pUART->STAT = stsMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the UART peripheral
|
||||
* @param pUART : The base of UART peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_UART_Init(LPC_USART_T *pUART);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the UART peripheral
|
||||
* @param pUART : The base of UART peripheral on the chip
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_UART_DeInit(LPC_USART_T *pUART);
|
||||
|
||||
/**
|
||||
* @brief Transmit a byte array through the UART peripheral (non-blocking)
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param data : Pointer to bytes to transmit
|
||||
* @param numBytes : Number of bytes to transmit
|
||||
* @return The actual number of bytes placed into the FIFO
|
||||
* @note This function places data into the transmit FIFO until either
|
||||
* all the data is in the FIFO or the FIFO is full. This function
|
||||
* will not block in the FIFO is full. The actual number of bytes
|
||||
* placed into the FIFO is returned. This function ignores errors.
|
||||
*/
|
||||
int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes);
|
||||
|
||||
/**
|
||||
* @brief Read data through the UART peripheral (non-blocking)
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param data : Pointer to bytes array to fill
|
||||
* @param numBytes : Size of the passed data array
|
||||
* @return The actual number of bytes read
|
||||
* @note This function reads data from the receive FIFO until either
|
||||
* all the data has been read or the passed buffer is completely full.
|
||||
* This function will not block. This function ignores errors.
|
||||
*/
|
||||
int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes);
|
||||
|
||||
/**
|
||||
* @brief Set baud rate for UART
|
||||
* @param pUART : The base of UART peripheral on the chip
|
||||
* @param baudrate: Baud rate to be set
|
||||
* @return Nothing
|
||||
*/
|
||||
void Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* @brief Transmit a byte array through the UART peripheral (blocking)
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param data : Pointer to data to transmit
|
||||
* @param numBytes : Number of bytes to transmit
|
||||
* @return The number of bytes transmitted
|
||||
* @note This function will send or place all bytes into the transmit
|
||||
* FIFO. This function will block until the last bytes are in the FIFO.
|
||||
*/
|
||||
int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes);
|
||||
|
||||
/**
|
||||
* @brief Read data through the UART peripheral (blocking)
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param data : Pointer to data array to fill
|
||||
* @param numBytes : Size of the passed data array
|
||||
* @return The size of the dat array
|
||||
* @note This function reads data from the receive FIFO until the passed
|
||||
* buffer is completely full. The function will block until full.
|
||||
* This function ignores errors.
|
||||
*/
|
||||
int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes);
|
||||
|
||||
/**
|
||||
* @brief UART receive-only interrupt handler for ring buffers
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param pRB : Pointer to ring buffer structure to use
|
||||
* @return Nothing
|
||||
* @note If ring buffer support is desired for the receive side
|
||||
* of data transfer, the UART interrupt should call this
|
||||
* function for a receive based interrupt status.
|
||||
*/
|
||||
void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB);
|
||||
|
||||
/**
|
||||
* @brief UART transmit-only interrupt handler for ring buffers
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param pRB : Pointer to ring buffer structure to use
|
||||
* @return Nothing
|
||||
* @note If ring buffer support is desired for the transmit side
|
||||
* of data transfer, the UART interrupt should call this
|
||||
* function for a transmit based interrupt status.
|
||||
*/
|
||||
void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB);
|
||||
|
||||
/**
|
||||
* @brief Populate a transmit ring buffer and start UART transmit
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param pRB : Pointer to ring buffer structure to use
|
||||
* @param data : Pointer to buffer to move to ring buffer
|
||||
* @param count : Number of bytes to move
|
||||
* @return The number of bytes placed into the ring buffer
|
||||
* @note Will move the data into the TX ring buffer and start the
|
||||
* transfer. If the number of bytes returned is less than the
|
||||
* number of bytes to send, the ring buffer is considered full.
|
||||
*/
|
||||
uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int count);
|
||||
|
||||
/**
|
||||
* @brief Copy data from a receive ring buffer
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param pRB : Pointer to ring buffer structure to use
|
||||
* @param data : Pointer to buffer to fill from ring buffer
|
||||
* @param bytes : Size of the passed buffer in bytes
|
||||
* @return The number of bytes placed into the ring buffer
|
||||
* @note Will move the data from the RX ring buffer up to the
|
||||
* the maximum passed buffer size. Returns 0 if there is
|
||||
* no data in the ring buffer.
|
||||
*/
|
||||
int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes);
|
||||
|
||||
/**
|
||||
* @brief UART receive/transmit interrupt handler for ring buffers
|
||||
* @param pUART : Pointer to selected UART peripheral
|
||||
* @param pRXRB : Pointer to transmit ring buffer
|
||||
* @param pTXRB : Pointer to receive ring buffer
|
||||
* @return Nothing
|
||||
* @note This provides a basic implementation of the UART IRQ
|
||||
* handler for support of a ring buffer implementation for
|
||||
* transmit and receive.
|
||||
*/
|
||||
void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __UART_540XX_H_ */
|
||||
Reference in New Issue
Block a user