mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 15:37:43 +00:00
Upstream merge to make new revision of PortaPack work (#206)
* Power: Turn off additional peripheral clock branches. * Update schematic with new symbol table and KiCad standard symbols. Fix up wires. * Schematic: Update power net labels. * Schematic: Update footprint names to match library changes. * Schematic: Update header vendor and part numbers. * Schematic: Specify (arbitrary) value for PDN# net. * Schematic: Remove fourth fiducial. Not standard practice, and was taking up valuable board space. * Schematic: Add reference oscillator -- options for clipped sine or HCMOS output. * Schematic: Update copyright year. * Schematic: Remove CLKOUT to CPLD. It was a half-baked idea. * Schematic: Add (experimental) GPS circuit. Add note about charging circuit. Update date and revision to match PCB. * PCB: Update from schematic change: now revision 20180819. Diff was extensive due to net renumbering... * PCB: Fix GPS courtyard to accommodate crazy solder paste recommendation in integration manual. PCB: Address DRC clearance violation between via and oscillator pad. * PCB: Update copyright on drawing. * Update schematic and PCB date and revision. * gitignore: Sublime Text editor project/workspace files * Power: Power up or power down peripheral clock at appropriate times, so firmware doesn't freeze... * Clocking: Fix incorrect shift for CGU IDIVx_CTRL.PD field. * LPC43xx: Add CGU IDIVx struct/union type. * Power: Switch off unused IDIV dividers. Make note of active IDIVs and their use. * HackRF Mode: Upgrade firmware to 2018.01.1 (API 1.02) * MAX V CPLD: Refactor class to look more like Xilinx CoolRunner II CPLD class. * MAX V CPLD: Add BYPASS, SAMPLE support. Rename enter_isp -> enable, exit_isp -> disable. Use SAMPLE at start of flash process, which somehow addresses the problem where CFM wouldn't load into SRAM (and become the active bitstream) after flashing. * MAX V CPLD: Reverse verify data checking logic to make it a little faster. * CPLD: After reprogramming flash, immediately clamp I/O signals, load to SRAM, and "execute" the new bitstream. * Si5351: Refactor code, make one of the registers more type-safe. Clock Manager: Track selected reference clock source for later use in user interface. * Clock Manager: Add note about PPM only affecting Si5351C PLLA, which always runs from the HackRF 25MHz crystal. It is assumed an external clock does not need adjustment, though I am open to being convinced otherwise... * PPM UI: Show "EXT" when showing PPM adjustment and reference clock is external. * CPLD: Add pins and logic for new PortaPack hardware feature(s). * CPLD: Bitstream to support new hardware features. * Clock Generator: Add a couple more setter methods for ClockControl registers. * Clock Manager: Use shared MCU CLKIN clock control configuration constant. * Clock Manager: Reduce MCU CLKIN driver current. 2mA should be plenty. * Clock Manager: Remove redundant clock generator output enable. * Bootstrap: Remove unnecessary ldscript hack to locate SPIFI mode change code in RAM. * Bootstrap: Get CPU operating at max frequency as soon as possible. Update SPIFI speed comment. Make some more LPC43xx types into unions with uint32_t. * Bootstrap: Explicitly configure IDIVB for SPIFI, despite LPC43xx bootloader setting it. * Clock Manager: Init peripherals before CPLD reconfig. Do the clock generator setup after, so we can check presence of PortaPack reference clock with the help of the latest CPLD bitstream. * Clock Manager: Reverse sense of conditional that determines crystal or non-crystal reference source. This is for an expected upcoming change where multiple external options can be differentiated. * Bootstrap: Consolidate clock configuration, update SPIFI rate comment. * Clock Manager: Use IDIVA for clock source for all peripherals, instead of PLL1. Should make switching easier going forward. Don't use IRC as clock during initial clock manager configuration. Until we switch to GP_CLKIN, we should go flat out... * ChibiOS M0: Change default clock speed to 204MHz, since bootstrap now maxes out clock speed before starting M0 execution. * PortaPack IO: Expose method to set reference oscillator enable pin. * Pin configuration: Do SPIFI pin config with other pins, in preparation for eliminating separate bootloader. * Pin configuration: Disable input buffers on pins that are never read. * Revert "ChibiOS M0: Change default clock speed to 204MHz, since bootstrap now maxes out clock speed before starting M0 execution." This reverts commit c0e2bb6cc4cc656769323bdbb8ee5a16d2d5bb03. * Remove unused board files. * Add LPC43xx functions. * chibios: Replace code with per-peripheral structs defining clocks, interrupts, and reset bits. * LPC43xx: Add MCPWM peripheral struct. * clock generator: Use recommended PLL reset register value. Datasheet recommends a value. AN619 is quiet on the topic, claims the low nibble is default 0b0000. * GPIO: Tweak masking of SCU function. I don't remember why I thought this was necessary... * HAL: Explicitly turn on timer peripheral clocks used as systicks, during init. * SCU: Add struct to hold pin configuration. * PAL: Add functions to address The Glitch. https://greatscottgadgets.com/2018/02-28-we-fixed-the-glitch/ * PAL/board: New IO initialization code Declare initial state for SCU pin config, GPIOs. Apply initial state during PAL init. Perform VAA slow turn-on to address The Glitch. * Merge M0 and M4 to eliminate need for bootstrap firmware During _early_init, detect if we're running on the M4 or M0. If M4: do M4-specific core initialization, reset peripherals, speed up SPIFI clock, start M0, go to sleep. If M0: do all the other things. * Pins: Miscellaneous SCU configuration tweaks. * Little code clarity improvement. * bootstrap: Remove, not necessary. * Clock Manager: Large re-working to support external references. * Fix merge conflicts
This commit is contained in:
@@ -54,6 +54,24 @@ ADCDriver ADCD1;
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC43XX_ADC_USE_ADC0
|
||||
static const adc_resources_t adc0_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_APB3_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1U << 0) },
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_APB3_ADC0_CFG, .stat = &LPC_CCU1->CLK_APB3_ADC0_STAT },
|
||||
.reset = { .output_index = 40 },
|
||||
.interrupt = { .irq = ADC0_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_ADC0_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_ADC_USE_ADC0 */
|
||||
|
||||
#if LPC43XX_ADC_USE_ADC1
|
||||
static const adc_resources_t adc1_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_APB3_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1U << 0) },
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_APB3_ADC1_CFG, .stat = &LPC_CCU1->CLK_APB3_ADC1_STAT },
|
||||
.reset = { .output_index = 41 },
|
||||
.interrupt = { .irq = ADC1_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_ADC1_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_ADC_USE_ADC1 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
@@ -129,6 +147,7 @@ void adc_lld_init(void) {
|
||||
adcObjectInit(&ADCD0);
|
||||
/* TODO: Implement */
|
||||
ADCD0.adc = LPC_ADC0;
|
||||
ADCD0.resources = &adc0_resources;
|
||||
#endif /* LPC43XX_ADC_USE_ADC0 */
|
||||
|
||||
#if LPC43XX_ADC_USE_ADC1
|
||||
@@ -136,6 +155,7 @@ void adc_lld_init(void) {
|
||||
adcObjectInit(&ADCD1);
|
||||
/* TODO: Implement */
|
||||
ADCD1.adc = LPC_ADC1;
|
||||
ADCD1.resources = &adc1_resources;
|
||||
#endif /* LPC43XX_ADC_USE_ADC1 */
|
||||
}
|
||||
|
||||
@@ -150,20 +170,10 @@ void adc_lld_start(ADCDriver *adcp) {
|
||||
|
||||
if (adcp->state == ADC_STOP) {
|
||||
/* Enables the peripheral.*/
|
||||
#if LPC43XX_ADC_USE_ADC0
|
||||
if (&ADCD0 == adcp) {
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.RUN = 1;
|
||||
LPC_CGU->BASE_APB3_CLK.PD = 0;
|
||||
nvicEnableVector(ADC0_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_ADC0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_ADC_USE_ADC0 */
|
||||
#if LPC43XX_ADC_USE_ADC1
|
||||
if (&ADCD1 == adcp) {
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.RUN = 1;
|
||||
LPC_CGU->BASE_APB3_CLK.PD = 0;
|
||||
nvicEnableVector(ADC1_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_ADC1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_ADC_USE_ADC1 */
|
||||
base_clock_enable(&adcp->resources->base);
|
||||
branch_clock_enable(&adcp->resources->branch);
|
||||
peripheral_reset(&adcp->resources->reset);
|
||||
interrupt_enable(&adcp->resources->interrupt);
|
||||
|
||||
/* Configures the peripheral.*/
|
||||
adcp->adc->CR =
|
||||
@@ -201,21 +211,10 @@ void adc_lld_stop(ADCDriver *adcp) {
|
||||
;
|
||||
|
||||
/* Disables the peripheral.*/
|
||||
#if LPC43XX_ADC_USE_ADC0
|
||||
if (&ADCD0 == adcp) {
|
||||
nvicDisableVector(ADC0_IRQn);
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_ADC_USE_ADC0 */
|
||||
|
||||
#if LPC43XX_ADC_USE_ADC1
|
||||
if (&ADCD1 == adcp) {
|
||||
nvicDisableVector(ADC1_IRQn);
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_ADC_USE_ADC1 */
|
||||
interrupt_disable(&adcp->resources->interrupt);
|
||||
peripheral_reset(&adcp->resources->reset);
|
||||
branch_clock_disable(&adcp->resources->branch);
|
||||
base_clock_disable(&adcp->resources->base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -95,6 +95,16 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for ADC configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
base_clock_regs_t base;
|
||||
branch_clock_regs_t branch;
|
||||
peripheral_reset_t reset;
|
||||
interrupt_config_t interrupt;
|
||||
} adc_resources_t;
|
||||
|
||||
typedef LPC_ADCx_Type* ADC_TypeDef;
|
||||
|
||||
/**
|
||||
@@ -235,6 +245,10 @@ struct ADCDriver {
|
||||
* @brief Pointer to the ADCx registers block.
|
||||
*/
|
||||
ADC_TypeDef adc;
|
||||
/**
|
||||
* @brief Pointer to the non-peripheral ADC resources.
|
||||
*/
|
||||
const adc_resources_t * resources;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@@ -32,6 +32,38 @@
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER0
|
||||
static const timer_resources_t timer0_resources = {
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_M4_TIMER0_CFG, .stat = &LPC_CCU1->CLK_M4_TIMER0_STAT },
|
||||
.reset = { .output_index = 32 },
|
||||
.interrupt = { .irq = TIMER0_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER0_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_GPT_USE_TIMER0 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER1
|
||||
static const timer_resources_t timer1_resources = {
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_M4_TIMER1_CFG, .stat = &LPC_CCU1->CLK_M4_TIMER1_STAT },
|
||||
.reset = { .output_index = 33 },
|
||||
.interrupt = { .irq = TIMER1_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER1_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_GPT_USE_TIMER1 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER2
|
||||
static const timer_resources_t timer2_resources = {
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_M4_TIMER2_CFG, .stat = &LPC_CCU1->CLK_M4_TIMER2_STAT },
|
||||
.reset = { .output_index = 34 },
|
||||
.interrupt = { .irq = TIMER2_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER2_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER3
|
||||
static const timer_resources_t timer3_resources = {
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_M4_TIMER3_CFG, .stat = &LPC_CCU1->CLK_M4_TIMER3_STAT },
|
||||
.reset = { .output_index = 35 },
|
||||
.interrupt = { .irq = TIMER3_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER3_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
@@ -158,24 +190,28 @@ void gpt_lld_init(void) {
|
||||
/* Driver initialization.*/
|
||||
gptObjectInit(&GPTD1);
|
||||
GPTD1.tmr = LPC_TIMER0;
|
||||
GPTD1.resources = &timer0_resources;
|
||||
#endif /* LPC43XX_GPT_USE_TIMER0 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER1
|
||||
/* Driver initialization.*/
|
||||
gptObjectInit(&GPTD2);
|
||||
GPTD2.tmr = LPC_TIMER1;
|
||||
GPTD2.resources = &timer1_resources;
|
||||
#endif /* LPC43XX_GPT_USE_TIMER1 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER2
|
||||
/* Driver initialization.*/
|
||||
gptObjectInit(&GPTD3);
|
||||
GPTD3.tmr = LPC_TIMER2;
|
||||
GPTD3.resources = &timer2_resources;
|
||||
#endif /* LPC43XX_GPT_USE_TIMER2 */
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER3
|
||||
/* Driver initialization.*/
|
||||
gptObjectInit(&GPTD4);
|
||||
GPTD4.tmr = LPC_TIMER3;
|
||||
GPTD4.resources = &timer3_resources;
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
}
|
||||
|
||||
@@ -190,30 +226,9 @@ void gpt_lld_start(GPTDriver *gptp) {
|
||||
|
||||
if (gptp->state == GPT_STOP) {
|
||||
/* Enables the peripheral.*/
|
||||
#if LPC43XX_GPT_USE_TIMER0
|
||||
if (&GPTD1 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG.RUN = 1;
|
||||
nvicEnableVector(TIMER0_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER0 */
|
||||
#if LPC43XX_GPT_USE_TIMER1
|
||||
if (&GPTD2 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG.RUN = 1;
|
||||
nvicEnableVector(TIMER1_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER1 */
|
||||
#if LPC43XX_GPT_USE_TIMER2
|
||||
if (&GPTD3 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG.RUN = 1;
|
||||
nvicEnableVector(TIMER2_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER2_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
#if LPC43XX_GPT_USE_TIMER3
|
||||
if (&GPTD4 == gptp) {
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG.RUN = 1;
|
||||
nvicEnableVector(TIMER3_IRQn, CORTEX_PRIORITY_MASK(LPC43XX_GPT_TIMER3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
branch_clock_enable(&gptp->resources->branch);
|
||||
peripheral_reset(&gptp->resources->reset);
|
||||
interrupt_enable(&gptp->resources->interrupt);
|
||||
}
|
||||
|
||||
/* Timer configuration.*/
|
||||
@@ -237,34 +252,9 @@ void gpt_lld_stop(GPTDriver *gptp) {
|
||||
gptp->tmr->MCR = 0;
|
||||
gptp->tmr->TCR = 0;
|
||||
|
||||
#if LPC43XX_GPT_USE_TIMER0
|
||||
if (&GPTD1 == gptp) {
|
||||
nvicDisableVector(TIMER0_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_TIMER0_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER0 */
|
||||
#if LPC43XX_GPT_USE_TIMER1
|
||||
if (&GPTD2 == gptp) {
|
||||
nvicDisableVector(TIMER1_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_TIMER1_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER1 */
|
||||
#if LPC43XX_GPT_USE_TIMER2
|
||||
if (&GPTD3 == gptp) {
|
||||
nvicDisableVector(TIMER2_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_TIMER2_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER2 */
|
||||
#if LPC43XX_GPT_USE_TIMER3
|
||||
if (&GPTD4 == gptp) {
|
||||
nvicDisableVector(TIMER3_IRQn);
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG.RUN = 0;
|
||||
}
|
||||
#endif /* LPC43XX_GPT_USE_TIMER3 */
|
||||
interrupt_disable(&gptp->resources->interrupt);
|
||||
peripheral_reset(&gptp->resources->reset);
|
||||
branch_clock_disable(&gptp->resources->branch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -135,6 +135,15 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for Timer configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
branch_clock_regs_t branch;
|
||||
peripheral_reset_t reset;
|
||||
interrupt_config_t interrupt;
|
||||
} timer_resources_t;
|
||||
|
||||
/**
|
||||
* @brief GPT frequency type.
|
||||
*/
|
||||
@@ -185,6 +194,10 @@ struct GPTDriver {
|
||||
* @brief Pointer to the TIMER registers block.
|
||||
*/
|
||||
LPC_TIMER_Type *tmr;
|
||||
/**
|
||||
* @brief Pointer to the non-peripheral Timer resources.
|
||||
*/
|
||||
const timer_resources_t * resources;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@@ -86,6 +86,22 @@ I2CDriver I2CD1;
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC43XX_I2C_USE_I2C0
|
||||
static const i2c_resources_t i2c0_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1) },
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_APB1_I2C0_CFG, .stat = &LPC_CCU1->CLK_APB1_I2C0_STAT },
|
||||
.reset = { .output_index = 48 },
|
||||
};
|
||||
#endif /* LPC43XX_I2C_USE_I2C0 */
|
||||
|
||||
#if LPC43XX_I2C_USE_I2C1
|
||||
static const i2c_resources_t i2c1_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_APB3_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 0) },
|
||||
.branch = { .cfg = &LPC_CCU1->CLK_APB3_I2C1_CFG, .stat = &LPC_CCU1->CLK_APB3_I2C1_STAT },
|
||||
.reset = { .output_index = 49 },
|
||||
};
|
||||
#endif /* LPC43XX_I2C_USE_I2C1 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
@@ -364,12 +380,14 @@ void i2c_lld_init(void) {
|
||||
i2cObjectInit(&I2CD0);
|
||||
I2CD0.thread = NULL;
|
||||
I2CD0.i2c = LPC_I2C0;
|
||||
I2CD0.resources = &i2c0_resources;
|
||||
#endif /* LPC43XX_I2C_USE_I2C0 */
|
||||
|
||||
#if LPC43XX_I2C_USE_I2C1 || defined(__DOXYGEN__)
|
||||
i2cObjectInit(&I2CD1);
|
||||
I2CD1.thread = NULL;
|
||||
I2CD1.i2c = LPC_I2C1;
|
||||
I2CD1.resources = &i2c1_resources;
|
||||
#endif /* LPC43XX_I2C_USE_I2C1 */
|
||||
}
|
||||
|
||||
@@ -385,19 +403,9 @@ void i2c_lld_start(I2CDriver *i2cp) {
|
||||
|
||||
/* TODO: Reset peripheral, enable clocks? */
|
||||
|
||||
#if LPC43XX_I2C_USE_I2C0 || defined(__DOXYGEN__)
|
||||
if (&I2CD0 == i2cp) {
|
||||
////LPC_CCU1->CLK_APB1_I2C0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB1_I2C0_CFG.RUN = 1;
|
||||
}
|
||||
#endif /* LPC43XX_I2C_USE_I2C0 */
|
||||
|
||||
#if LPC43XX_I2C_USE_I2C1 || defined(__DOXYGEN__)
|
||||
if (&I2CD1 == i2cp) {
|
||||
////LPC_CCU1->CLK_APB3_I2C1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_I2C1_CFG.RUN = 1;
|
||||
}
|
||||
#endif /* LPC43XX_I2C_USE_I2C1 */
|
||||
base_clock_enable(&i2cp->resources->base);
|
||||
branch_clock_enable(&i2cp->resources->branch);
|
||||
peripheral_reset(&i2cp->resources->reset);
|
||||
|
||||
i2c_periph_set_clock(dp, i2cp->config->high_count, i2cp->config->low_count);
|
||||
i2c_periph_enable(dp);
|
||||
@@ -441,9 +449,16 @@ void i2c_lld_stop(I2CDriver *i2cp) {
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicDisableVector(I2C0_IRQn);
|
||||
#endif
|
||||
i2c_periph_disable(dp);
|
||||
LPC_CCU1->CLK_APB1_I2C0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB1_I2C0_CFG.RUN = 0;
|
||||
#if defined(LPC43XX_M0)
|
||||
#if LPC43XX_I2C_USE_I2C1
|
||||
if( I2CD1.state == I2C_STOP ) {
|
||||
#endif
|
||||
// TODO: This won't work if the I2C peripherals are split between cores!
|
||||
nvicDisableVector(I2C0_OR_I2C1_IRQn);
|
||||
#if LPC43XX_I2C_USE_I2C1
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /* LPC43XX_I2C_USE_I2C0 */
|
||||
|
||||
@@ -452,11 +467,23 @@ void i2c_lld_stop(I2CDriver *i2cp) {
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicDisableVector(I2C1_IRQn);
|
||||
#endif
|
||||
i2c_periph_disable(dp);
|
||||
LPC_CCU1->CLK_APB3_I2C1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_I2C1_CFG.RUN = 0;
|
||||
#if defined(LPC43XX_M0)
|
||||
#if LPC43XX_I2C_USE_I2C0
|
||||
if( I2CD0.state == I2C_STOP ) {
|
||||
#endif
|
||||
// TODO: This won't work if the I2C peripherals are split between cores!
|
||||
nvicDisableVector(I2C0_OR_I2C1_IRQn);
|
||||
#if LPC43XX_I2C_USE_I2C0
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /* LPC43XX_I2C_USE_I2C1 */
|
||||
|
||||
i2c_periph_disable(dp);
|
||||
peripheral_reset(&i2cp->resources->reset);
|
||||
branch_clock_disable(&i2cp->resources->branch);
|
||||
base_clock_disable(&i2cp->resources->base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -96,6 +96,15 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for I2C configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
base_clock_regs_t base;
|
||||
branch_clock_regs_t branch;
|
||||
peripheral_reset_t reset;
|
||||
} i2c_resources_t;
|
||||
|
||||
typedef LPC_I2Cx_Type* I2C_TypeDef;
|
||||
|
||||
/**
|
||||
@@ -181,6 +190,10 @@ struct I2CDriver {
|
||||
* @brief Pointer to the I2Cx registers block.
|
||||
*/
|
||||
I2C_TypeDef i2c;
|
||||
/**
|
||||
* @brief Pointer to the non-peripheral I2C resources.
|
||||
*/
|
||||
const i2c_resources_t * resources;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright (C) 2018 Jared Boone, ShareBrained Technology
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
void peripheral_reset(const peripheral_reset_t* const reset) {
|
||||
const size_t register_index = (reset->output_index >> 5) & 1;
|
||||
const size_t bit_shift = reset->output_index & 0x1f;
|
||||
const uint32_t mask = (1U << bit_shift);
|
||||
LPC_RGU->RESET_CTRL[register_index] = mask | (~LPC_RGU->RESET_ACTIVE_STATUS[register_index]);
|
||||
while((LPC_RGU->RESET_ACTIVE_STATUS[register_index] & mask) == 0);
|
||||
}
|
||||
|
||||
void base_clock_enable(const base_clock_regs_t* const base) {
|
||||
if( base->clk->PD ) {
|
||||
base->clk->AUTOBLOCK = 1;
|
||||
//base->clk->CLK_SEL = ?;
|
||||
base->clk->PD = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void base_clock_disable(const base_clock_regs_t* const base) {
|
||||
if( !base->clk->PD ) {
|
||||
// Are all branch clocks switched off?
|
||||
// NOTE: Field stat must be valid memory address.
|
||||
// NOTE: Field stat_mask is zero if there's no means to check if a base clock is in use.
|
||||
if( (*base->stat & base->stat_mask) == 0 ) {
|
||||
base->clk->PD = 1;
|
||||
//base->clk->CLK_SEL = IRC?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void branch_clock_enable(const branch_clock_regs_t* const branch) {
|
||||
if( !branch->stat->RUN ) {
|
||||
branch->cfg->AUTO = 1;
|
||||
branch->cfg->RUN = 1;
|
||||
while(!branch->stat->RUN);
|
||||
}
|
||||
}
|
||||
|
||||
void branch_clock_disable(const branch_clock_regs_t* const branch) {
|
||||
if( branch->stat->RUN ) {
|
||||
branch->cfg->RUN = 0;
|
||||
while(branch->stat->RUN);
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt_enable(const interrupt_config_t* const interrupt) {
|
||||
nvicEnableVector(interrupt->irq, interrupt->priority_mask);
|
||||
}
|
||||
|
||||
void interrupt_disable(const interrupt_config_t* const interrupt) {
|
||||
nvicDisableVector(interrupt->irq);
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (C) 2018 Jared Boone, ShareBrained Technology
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LPC43XX_H_
|
||||
#define _LPC43XX_H_
|
||||
|
||||
typedef struct {
|
||||
LPC_CGU_BASE_CLK_Type* clk;
|
||||
__I uint32_t* stat;
|
||||
uint32_t stat_mask;
|
||||
} base_clock_regs_t;
|
||||
|
||||
typedef struct {
|
||||
LPC_CCU1_CFG_160_Type* cfg;
|
||||
LPC_CCU_STAT_Type* stat;
|
||||
} branch_clock_regs_t;
|
||||
|
||||
typedef struct {
|
||||
uint_fast8_t output_index;
|
||||
} peripheral_reset_t;
|
||||
|
||||
typedef struct {
|
||||
IRQn_Type irq;
|
||||
uint32_t priority_mask;
|
||||
} interrupt_config_t;
|
||||
|
||||
void peripheral_reset(const peripheral_reset_t* const reset);
|
||||
|
||||
void base_clock_enable(const base_clock_regs_t* const base);
|
||||
void base_clock_disable(const base_clock_regs_t* const base);
|
||||
|
||||
void branch_clock_enable(const branch_clock_regs_t* const branch);
|
||||
void branch_clock_disable(const branch_clock_regs_t* const branch);
|
||||
|
||||
void interrupt_enable(const interrupt_config_t* const interrupt);
|
||||
void interrupt_disable(const interrupt_config_t* const interrupt);
|
||||
|
||||
#endif /* _LPC43XX_H_ */
|
@@ -98,11 +98,14 @@ typedef struct {
|
||||
uint32_t RESERVED0 : 3;
|
||||
} LPC_CGU_FREQ_MON_Type;
|
||||
|
||||
typedef struct {
|
||||
__IO uint32_t ENABLE : 1;
|
||||
__IO uint32_t BYPASS : 1;
|
||||
__IO uint32_t HF : 1;
|
||||
uint32_t RESERVED0 : 29;
|
||||
typedef union {
|
||||
struct {
|
||||
__IO uint32_t ENABLE : 1;
|
||||
__IO uint32_t BYPASS : 1;
|
||||
__IO uint32_t HF : 1;
|
||||
uint32_t RESERVED0 : 29;
|
||||
};
|
||||
__IO uint32_t word;
|
||||
} LPC_CGU_XTAL_OSC_CTRL_Type;
|
||||
|
||||
typedef struct {
|
||||
@@ -146,18 +149,21 @@ typedef struct {
|
||||
__IO uint32_t CLK_SEL : 5;
|
||||
uint32_t RESERVED3 : 3;
|
||||
} LPC_CGU_PLL1_CTRL_Type;
|
||||
/*
|
||||
typedef struct {
|
||||
__IO uint32_t PD : 1;
|
||||
uint32_t RESERVED0 : 1;
|
||||
__IO uint32_t IDIV : 2;
|
||||
uint32_t RESERVED1 : 7;
|
||||
__IO uint32_t AUTOBLOCK : 1;
|
||||
uint32_t RESERVED2 : 12;
|
||||
__IO uint32_t CLK_SEL : 5;
|
||||
uint32_t RESERVED3 : 3;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
__IO uint32_t PD : 1;
|
||||
uint32_t RESERVED0 : 1;
|
||||
__IO uint32_t IDIV : 2;
|
||||
uint32_t RESERVED1 : 7;
|
||||
__IO uint32_t AUTOBLOCK : 1;
|
||||
uint32_t RESERVED2 : 12;
|
||||
__IO uint32_t CLK_SEL : 5;
|
||||
uint32_t RESERVED3 : 3;
|
||||
};
|
||||
__IO uint32_t word;
|
||||
} LPC_CGU_IDIVx_CTRL_Type;
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
__I uint32_t PD : 1;
|
||||
uint32_t RESERVED0 : 10;
|
||||
@@ -167,13 +173,16 @@ typedef struct {
|
||||
uint32_t RESERVED2 : 3;
|
||||
} LPC_CGU_BASE_SAFE_CLK_Type;
|
||||
|
||||
typedef struct {
|
||||
__IO uint32_t PD : 1;
|
||||
uint32_t RESERVED0 : 10;
|
||||
__IO uint32_t AUTOBLOCK : 1;
|
||||
uint32_t RESERVED1 : 12;
|
||||
__IO uint32_t CLK_SEL : 5;
|
||||
uint32_t RESERVED2 : 3;
|
||||
typedef union {
|
||||
struct {
|
||||
__IO uint32_t PD : 1;
|
||||
uint32_t RESERVED0 : 10;
|
||||
__IO uint32_t AUTOBLOCK : 1;
|
||||
uint32_t RESERVED1 : 12;
|
||||
__IO uint32_t CLK_SEL : 5;
|
||||
uint32_t RESERVED2 : 3;
|
||||
};
|
||||
__IO uint32_t word;
|
||||
} LPC_CGU_BASE_CLK_Type;
|
||||
|
||||
typedef struct {
|
||||
@@ -191,11 +200,11 @@ typedef struct {
|
||||
__IO uint32_t PLL0AUDIO_FRAC;
|
||||
__I uint32_t PLL1_STAT; /* +0x040 */
|
||||
__IO uint32_t PLL1_CTRL;
|
||||
__IO uint32_t IDIVA_CTRL;
|
||||
__IO uint32_t IDIVB_CTRL;
|
||||
__IO uint32_t IDIVC_CTRL; /* +0x050 */
|
||||
__IO uint32_t IDIVD_CTRL;
|
||||
__IO uint32_t IDIVE_CTRL;
|
||||
LPC_CGU_IDIVx_CTRL_Type IDIVA_CTRL;
|
||||
LPC_CGU_IDIVx_CTRL_Type IDIVB_CTRL;
|
||||
LPC_CGU_IDIVx_CTRL_Type IDIVC_CTRL; /* +0x050 */
|
||||
LPC_CGU_IDIVx_CTRL_Type IDIVD_CTRL;
|
||||
LPC_CGU_IDIVx_CTRL_Type IDIVE_CTRL;
|
||||
LPC_CGU_BASE_SAFE_CLK_Type BASE_SAFE_CLK;
|
||||
LPC_CGU_BASE_CLK_Type BASE_USB0_CLK; /* +0x060 */
|
||||
LPC_CGU_BASE_CLK_Type BASE_PERIPH_CLK;
|
||||
@@ -1065,6 +1074,47 @@ typedef struct {
|
||||
__IO uint32_t CTCR;
|
||||
} LPC_TIMER_Type;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ----- MOTOCONPWM -----
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Product name title=UM10503 Chapter title=LPC43xx Motor Control PWM (MOTOCONPWM) Modification date=7/26/2017 Major revision=2 Minor revision=3
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
__I uint32_t CON;
|
||||
__O uint32_t CON_SET;
|
||||
__O uint32_t CON_CLR;
|
||||
__I uint32_t CAPCON;
|
||||
__O uint32_t CAPCON_SET;
|
||||
__O uint32_t CAPCON_CLR;
|
||||
__IO uint32_t TC0;
|
||||
__IO uint32_t TC1;
|
||||
__IO uint32_t TC2;
|
||||
__IO uint32_t LIM0;
|
||||
__IO uint32_t LIM1;
|
||||
__IO uint32_t LIM2;
|
||||
__IO uint32_t MAT0;
|
||||
__IO uint32_t MAT1;
|
||||
__IO uint32_t MAT2;
|
||||
__IO uint32_t DT;
|
||||
__IO uint32_t MCCP;
|
||||
__I uint32_t CAP0;
|
||||
__I uint32_t CAP1;
|
||||
__I uint32_t CAP2;
|
||||
__I uint32_t INTEN;
|
||||
__O uint32_t INTEN_SET;
|
||||
__O uint32_t INTEN_CLR;
|
||||
__I uint32_t CNTCON;
|
||||
__O uint32_t CNTCON_SET;
|
||||
__O uint32_t CNTCON_CLR;
|
||||
__I uint32_t INTF;
|
||||
__O uint32_t INTF_SET;
|
||||
__O uint32_t INTF_CLR;
|
||||
__O uint32_t CAP_CLR;
|
||||
} LPC_MCPWM_Type;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ----- RITIMER -----
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -1409,6 +1459,7 @@ typedef struct {
|
||||
#define LPC_USART3 ((LPC_USART_Type *) LPC_USART3_BASE)
|
||||
#define LPC_TIMER2 ((LPC_TIMER_Type *) LPC_TIMER2_BASE)
|
||||
#define LPC_TIMER3 ((LPC_TIMER_Type *) LPC_TIMER3_BASE)
|
||||
#define LPC_MCPWM ((LPC_MCPWM_Type *) LPC_MCPWM_BASE)
|
||||
#define LPC_SSP1 ((LPC_SSPx_Type *) LPC_SSP1_BASE)
|
||||
#define LPC_I2C1 ((LPC_I2Cx_Type *) LPC_I2C1_BASE)
|
||||
#define LPC_ADC0 ((LPC_ADCx_Type *) LPC_ADC0_BASE)
|
||||
|
@@ -40,10 +40,74 @@
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static const scu_config_t pin_config_vaa_enablex_pwm = { .MODE=1, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 };
|
||||
static const scu_config_t pin_config_vaa_enablex_gpio = { .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 };
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/* VAA powers:
|
||||
* MAX5864 analog section.
|
||||
* MAX2837 registers and other functions.
|
||||
* RFFC5072 analog section.
|
||||
*
|
||||
* Beware that power applied to pins of the MAX2837 may
|
||||
* show up on VAA and start powering other components on the
|
||||
* VAA net. So turn on VAA before driving pins from MCU to
|
||||
* MAX2837.
|
||||
*/
|
||||
static void vaa_power_on(void) {
|
||||
/* Very twitchy process for powering up VAA without glitching the 3.3V rail, which can send the
|
||||
* microcontroller into reset.
|
||||
*
|
||||
* Controlling timing while running from SPIFI flash is tricky, hence use of a PWM peripheral...
|
||||
*/
|
||||
|
||||
/* Configure and enable MOTOCONPWM peripheral clocks.
|
||||
* Assume IDIVC is running the post-bootloader configuration, outputting 96MHz derived from PLL1.
|
||||
*/
|
||||
LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG.RUN = true;
|
||||
|
||||
/* Combination of pulse duration and duty cycle was arrived at empirically, to keep supply glitching
|
||||
* to +/- 0.15V.
|
||||
*/
|
||||
const uint32_t cycle_period = 128;
|
||||
const uint32_t enable_period = 10;
|
||||
LPC_MCPWM->TC2 = 0;
|
||||
LPC_MCPWM->MAT2 = cycle_period - enable_period;
|
||||
LPC_MCPWM->LIM2 = cycle_period;
|
||||
|
||||
/* Switch !VAA_ENABLE pin from GPIO to MOTOCONPWM peripheral output, now that the peripheral is configured. */
|
||||
LPC_SCU->SFSP[5][ 0] = pin_config_vaa_enablex_pwm.word; // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
|
||||
|
||||
/* Start the PWM operation. */
|
||||
LPC_MCPWM->CON_SET = (1 << 16);
|
||||
|
||||
/* Wait until VAA rises to approximately 90% of final voltage. */
|
||||
/* Timing assumes we're running immediately after the bootloader: 96 MHz from IRC+PLL1
|
||||
*/
|
||||
{ volatile uint32_t delay = 12000; while(delay--); }
|
||||
|
||||
/* Hold !VAA_ENABLE active using a GPIO, so we can reclaim and shut down the MOTOCONPWM peripheral. */
|
||||
LPC_GPIO->CLR[2] = (1 << 9); // !VAA_ENABLE
|
||||
LPC_GPIO->DIR[2] |= (1 << 9);
|
||||
LPC_SCU->SFSP[5][ 0] = pin_config_vaa_enablex_gpio.word; // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
|
||||
|
||||
/* Reset the MOTOCONPWM peripheral. */
|
||||
LPC_RGU->RESET_CTRL[1] = (1U << 6);
|
||||
|
||||
/* Shut down the MOTOCONPWM clocks. */
|
||||
LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG.RUN = false;
|
||||
}
|
||||
|
||||
static void vaa_power_off(void) {
|
||||
// TODO: There's a lot of other stuff that must be done to prevent
|
||||
// leakage from +3V3 into VAA.
|
||||
LPC_GPIO->W2[9] = 1;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
@@ -52,6 +116,8 @@
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
/**
|
||||
* @brief LPC43xx I/O ports configuration.
|
||||
* @details Ports 0 through 8.
|
||||
@@ -65,6 +131,12 @@ void _pal_lld_init(const PALConfig *config) {
|
||||
LPC_GPIO->PIN[i] = config->P[i].data;
|
||||
LPC_GPIO->DIR[i] = config->P[i].dir;
|
||||
}
|
||||
|
||||
for(size_t i=0; i<ARRAY_SIZE(config->SCU); i++) {
|
||||
LPC_SCU->SFSP[config->SCU[i].port][config->SCU[i].pin] = config->SCU[i].config.word;
|
||||
}
|
||||
|
||||
vaa_power_on();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -51,6 +51,27 @@ typedef struct {
|
||||
uint32_t dir;
|
||||
} gpio_setup_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint16_t MODE : 3;
|
||||
uint16_t EPD : 1;
|
||||
uint16_t EPUN : 1;
|
||||
uint16_t EHS : 1;
|
||||
uint16_t EZI : 1;
|
||||
uint16_t ZIF : 1;
|
||||
uint16_t RESERVED0 : 8;
|
||||
};
|
||||
uint16_t word;
|
||||
};
|
||||
} scu_config_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t port;
|
||||
uint8_t pin;
|
||||
scu_config_t config;
|
||||
} scu_setup_t;
|
||||
|
||||
/**
|
||||
* @brief Generic I/O ports static initializer.
|
||||
* @details An instance of this structure must be passed to @p palInit() at
|
||||
@@ -63,6 +84,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
/** @brief GPIO setup data.*/
|
||||
gpio_setup_t P[8];
|
||||
scu_setup_t SCU[86];
|
||||
} PALConfig;
|
||||
|
||||
/**
|
||||
|
@@ -47,6 +47,16 @@ SDCDriver SDCD1;
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SDC_USE_SDC1
|
||||
static const sdio_resources_t sdio_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_SDIO_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = 0 },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_SDIO_CFG, .stat = &LPC_CCU1->CLK_M4_SDIO_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_SDIO_CFG, .stat = &LPC_CCU2->CLK_SDIO_STAT },
|
||||
.reset = { .output_index = 20 },
|
||||
.interrupt = { .irq = SDIO_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
@@ -561,6 +571,7 @@ CH_IRQ_HANDLER(SDIO_IRQHandler) {
|
||||
void sdc_lld_init(void) {
|
||||
|
||||
sdcObjectInit(&SDCD1);
|
||||
SDCD1.resources = &sdio_resources;
|
||||
SDCD1.thread = NULL;
|
||||
|
||||
/* Assuming there's a global reset when the hardware is initialized.
|
||||
@@ -578,10 +589,12 @@ void sdc_lld_init(void) {
|
||||
void sdc_lld_start(SDCDriver *sdcp) {
|
||||
|
||||
if (sdcp->state == BLK_STOP) {
|
||||
LPC_SDMMC->CLKENA = (1U << 16); /* CCLK_LOW_POWER */
|
||||
base_clock_enable(&sdcp->resources->base);
|
||||
branch_clock_enable(&sdcp->resources->branch_register_if);
|
||||
branch_clock_enable(&sdcp->resources->branch_peripheral);
|
||||
peripheral_reset(&sdcp->resources->reset);
|
||||
|
||||
LPC_CCU1->CLK_M4_SDIO_CFG.RUN = 1;
|
||||
LPC_CGU->BASE_SDIO_CLK.PD = 0;
|
||||
LPC_SDMMC->CLKENA = (1U << 16); /* CCLK_LOW_POWER */
|
||||
|
||||
sdio_reset();
|
||||
sdio_reset_card();
|
||||
@@ -623,8 +636,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
|
||||
sdio_interrupts_set_mask(0);
|
||||
sdio_interrupts_clear();
|
||||
|
||||
nvicEnableVector(SDIO_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SDC_SDIO_IRQ_PRIORITY));
|
||||
interrupt_enable(&sdcp->resources->interrupt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,7 +650,7 @@ void sdc_lld_start(SDCDriver *sdcp) {
|
||||
void sdc_lld_stop(SDCDriver *sdcp) {
|
||||
|
||||
if (sdcp->state != BLK_STOP) {
|
||||
nvicDisableVector(SDIO_IRQn);
|
||||
interrupt_disable(&sdcp->resources->interrupt);
|
||||
|
||||
/* Quickest way to return peripheral and card to known (and low power)
|
||||
* state is to reset both. Right?
|
||||
@@ -646,9 +658,10 @@ void sdc_lld_stop(SDCDriver *sdcp) {
|
||||
sdio_reset();
|
||||
sdio_reset_card();
|
||||
|
||||
LPC_CGU->BASE_SDIO_CLK.PD = 1;
|
||||
LPC_CCU1->CLK_M4_SDIO_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_SDIO_CFG.RUN = 0;
|
||||
peripheral_reset(&sdcp->resources->reset);
|
||||
branch_clock_disable(&sdcp->resources->branch_peripheral);
|
||||
branch_clock_disable(&sdcp->resources->branch_register_if);
|
||||
base_clock_disable(&sdcp->resources->base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -76,6 +76,17 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for SDIO configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
base_clock_regs_t base;
|
||||
branch_clock_regs_t branch_register_if;
|
||||
branch_clock_regs_t branch_peripheral;
|
||||
peripheral_reset_t reset;
|
||||
interrupt_config_t interrupt;
|
||||
} sdio_resources_t;
|
||||
|
||||
/**
|
||||
* @brief Type of SDIO bus mode.
|
||||
*/
|
||||
@@ -149,6 +160,10 @@ struct SDCDriver {
|
||||
*/
|
||||
uint32_t rca;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the non-peripheral SDIO resources.
|
||||
*/
|
||||
const sdio_resources_t * resources;
|
||||
/**
|
||||
* @brief Thread waiting for I/O completion IRQ.
|
||||
*/
|
||||
|
@@ -63,6 +63,48 @@ static const SerialConfig default_config = {
|
||||
FCR_TRIGGER0
|
||||
};
|
||||
|
||||
#if LPC_SERIAL_USE_USART0
|
||||
static const uart_resources_t usart0_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_UART0_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 4) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_USART0_CFG, .stat = &LPC_CCU1->CLK_M4_USART0_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB0_USART0_CFG, .stat = &LPC_CCU2->CLK_APB0_USART0_STAT },
|
||||
.reset = { .output_index = 44 },
|
||||
.interrupt = { .irq = USART0_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART0_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
static const uart_resources_t uart1_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_UART1_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 3) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_UART1_CFG, .stat = &LPC_CCU1->CLK_M4_UART1_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB0_UART1_CFG, .stat = &LPC_CCU2->CLK_APB0_UART1_STAT },
|
||||
.reset = { .output_index = 45 },
|
||||
.interrupt = { .irq = UART1_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART2
|
||||
static const uart_resources_t usart2_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_UART2_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 2) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_USART2_CFG, .stat = &LPC_CCU1->CLK_M4_USART2_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB2_USART2_CFG, .stat = &LPC_CCU2->CLK_APB2_USART2_STAT },
|
||||
.reset = { .output_index = 46 },
|
||||
#if defined(LPC43XX_M4)
|
||||
.interrupt = { .irq = USART2_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
|
||||
#endif
|
||||
#if defined(LPC43XX_M0)
|
||||
.interrupt = { .irq = USART2_OR_C_CAN1_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART3
|
||||
static const uart_resources_t usart3_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_UART3_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 1) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_USART3_CFG, .stat = &LPC_CCU1->CLK_M4_USART3_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB2_USART3_CFG, .stat = &LPC_CCU2->CLK_APB2_USART3_STAT },
|
||||
.reset = { .output_index = 47 },
|
||||
.interrupt = { .irq = USART3_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART3_IRQ_PRIORITY) },
|
||||
};
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
@@ -337,21 +379,25 @@ void sd_lld_init(void) {
|
||||
#if LPC_SERIAL_USE_USART0
|
||||
sdObjectInit(&SD1, NULL, notify1);
|
||||
SD1.uart = LPC_USART0;
|
||||
SD1.resources = &usart0_resources;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
sdObjectInit(&SD2, NULL, notify2);
|
||||
SD2.uart = (LPC_USART_Type *) LPC_UART1;
|
||||
SD2.resources = &uart1_resources;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_USART2
|
||||
sdObjectInit(&SD3, NULL, notify3);
|
||||
SD3.uart = LPC_USART2;
|
||||
SD3.resources = &usart2_resources;
|
||||
#endif
|
||||
|
||||
#if LPC_SERIAL_USE_USART3
|
||||
sdObjectInit(&SD4, NULL, notify4);
|
||||
SD4.uart = LPC_USART3;
|
||||
SD4.resources = &usart3_resources;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -371,48 +417,11 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
config = &default_config;
|
||||
|
||||
if (sdp->state == SD_STOP) {
|
||||
#if LPC_SERIAL_USE_USART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU1->CLK_M4_USART0_CFG.RUN = 1; /* Register interface branch clock. */
|
||||
LPC_CGU->BASE_UART0_CLK.PD = 0; /* Peripheral base clock. */
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG.RUN = 1; /* Peripheral branch clock. */
|
||||
nvicEnableVector(USART0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_USART0_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU1->CLK_M4_UART1_CFG.RUN = 1; /* Register interface branch clock. */
|
||||
LPC_CGU->BASE_UART1_CLK.PD = 0; /* Peripheral base clock. */
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG.RUN = 1; /* Peripheral branch clock. */
|
||||
nvicEnableVector(UART1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU1->CLK_M4_USART2_CFG.RUN = 1; /* Register interface branch clock. */
|
||||
LPC_CGU->BASE_UART2_CLK.PD = 0; /* Peripheral base clock. */
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG.RUN = 1; /* Peripheral branch clock. */
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicEnableVector(USART2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY));
|
||||
#endif
|
||||
#if defined(LPC43XX_M0)
|
||||
nvicEnableVector(USART2_OR_C_CAN1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU1->CLK_M4_USART3_CFG.RUN = 1; /* Register interface branch clock. */
|
||||
LPC_CGU->BASE_UART3_CLK.PD = 0; /* Peripheral base clock. */
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG.RUN = 1; /* Peripheral branch clock. */
|
||||
nvicEnableVector(USART3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SERIAL_USART3_IRQ_PRIORITY));
|
||||
}
|
||||
#endif
|
||||
base_clock_enable(&sdp->resources->base);
|
||||
branch_clock_enable(&sdp->resources->branch_register_if);
|
||||
branch_clock_enable(&sdp->resources->branch_peripheral);
|
||||
peripheral_reset(&sdp->resources->reset);
|
||||
interrupt_enable(&sdp->resources->interrupt);
|
||||
}
|
||||
uart_init(sdp, config);
|
||||
}
|
||||
@@ -429,56 +438,12 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
|
||||
void sd_lld_stop(SerialDriver *sdp) {
|
||||
|
||||
if (sdp->state == SD_READY) {
|
||||
uart_deinit(sdp->uart);
|
||||
#if LPC_SERIAL_USE_USART0
|
||||
if (&SD1 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG.AUTO = 1; /* Peripheral branch clock. */
|
||||
LPC_CCU2->CLK_APB0_USART0_CFG.RUN = 0;
|
||||
LPC_CGU->BASE_UART0_CLK.PD = 1; /* Peripheral base clock. */
|
||||
LPC_CCU1->CLK_M4_USART0_CFG.AUTO = 1; /* Register interface branch clock. */
|
||||
LPC_CCU1->CLK_M4_USART0_CFG.RUN = 0;
|
||||
nvicDisableVector(USART0_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_UART1
|
||||
if (&SD2 == sdp) {
|
||||
LPC_CCU2->CLK_APB0_UART1_CFG.AUTO = 1; /* Peripheral branch clock. */
|
||||
LPC_CCU2->CLK_APB0_UART0_CFG.RUN = 0;
|
||||
LPC_CGU->BASE_UART1_CLK.PD = 1; /* Peripheral base clock. */
|
||||
LPC_CCU1->CLK_M4_UART1_CFG.AUTO = 1; /* Register interface branch clock. */
|
||||
LPC_CCU1->CLK_M4_UART1_CFG.RUN = 0;
|
||||
nvicDisableVector(UART1_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART2
|
||||
if (&SD3 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG.AUTO = 1; /* Peripheral branch clock. */
|
||||
LPC_CCU2->CLK_APB2_USART2_CFG.RUN = 0;
|
||||
LPC_CGU->BASE_UART2_CLK.PD = 1; /* Peripheral base clock. */
|
||||
LPC_CCU1->CLK_M4_USART2_CFG.AUTO = 1; /* Register interface branch clock. */
|
||||
LPC_CCU1->CLK_M4_USART2_CFG.RUN = 0;
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicDisableVector(USART2_IRQn);
|
||||
#endif
|
||||
#if defined(LPC43XX_M0)
|
||||
nvicDisableVector(USART2_OR_C_CAN1_IRQn);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if LPC_SERIAL_USE_USART3
|
||||
if (&SD4 == sdp) {
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG.AUTO = 1; /* Peripheral branch clock. */
|
||||
LPC_CCU2->CLK_APB2_USART3_CFG.RUN = 0;
|
||||
LPC_CGU->BASE_UART3_CLK.PD = 1; /* Peripheral base clock. */
|
||||
LPC_CCU1->CLK_M4_USART3_CFG.AUTO = 1; /* Register interface branch clock. */
|
||||
LPC_CCU1->CLK_M4_USART3_CFG.RUN = 0;
|
||||
nvicDisableVector(USART3_IRQn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
uart_deinit(&sdp->uart);
|
||||
interrupt_disable(&sdp->resources->interrupt);
|
||||
peripheral_reset(&sdp->resources->reset);
|
||||
branch_clock_disable(&sdp->resources->branch_peripheral);
|
||||
branch_clock_disable(&sdp->resources->branch_register_if);
|
||||
base_clock_disable(&sdp->resources->base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -257,6 +257,17 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for UART configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
base_clock_regs_t base;
|
||||
branch_clock_regs_t branch_register_if;
|
||||
branch_clock_regs_t branch_peripheral;
|
||||
peripheral_reset_t reset;
|
||||
interrupt_config_t interrupt;
|
||||
} uart_resources_t;
|
||||
|
||||
/**
|
||||
* @brief LPC Serial Driver configuration structure.
|
||||
* @details An instance of this structure must be passed to @p sdStart()
|
||||
@@ -294,7 +305,9 @@ typedef struct {
|
||||
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
|
||||
/* End of the mandatory fields.*/ \
|
||||
/* Pointer to the UART registers block.*/ \
|
||||
LPC_USART_Type *uart;
|
||||
LPC_USART_Type *uart; \
|
||||
/* Pointer to the non-peripheral SSP resources.*/ \
|
||||
const ssp_resources_t * resources;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
|
@@ -48,6 +48,24 @@ SPIDriver SPID2;
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if LPC_SPI_USE_SSP0
|
||||
static const ssp_resources_t ssp0_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_SSP0_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1U << 6) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_SSP0_CFG, .stat = &LPC_CCU1->CLK_M4_SSP0_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB0_SSP0_CFG, .stat = &LPC_CCU2->CLK_APB0_SSP0_STAT },
|
||||
.reset = { .output_index = 50 },
|
||||
};
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC_SPI_USE_SSP1
|
||||
static const ssp_resources_t ssp1_resources = {
|
||||
.base = { .clk = &LPC_CGU->BASE_SSP1_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1U << 5) },
|
||||
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_SSP1_CFG, .stat = &LPC_CCU1->CLK_M4_SSP1_STAT },
|
||||
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB2_SSP1_CFG, .stat = &LPC_CCU2->CLK_APB2_SSP1_STAT },
|
||||
.reset = { .output_index = 51 },
|
||||
};
|
||||
#endif /* LPC_SPI_USE_SSP1 */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
@@ -194,11 +212,13 @@ void spi_lld_init(void) {
|
||||
#if LPC_SPI_USE_SSP0
|
||||
spiObjectInit(&SPID1);
|
||||
SPID1.ssp = LPC_SSP0;
|
||||
SPID1.resources = &ssp0_resources;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
|
||||
#if LPC_SPI_USE_SSP1
|
||||
spiObjectInit(&SPID2);
|
||||
SPID2.ssp = LPC_SSP1;
|
||||
SPID2.resources = &ssp1_resources;
|
||||
#endif /* LPC_SPI_USE_SSP0 */
|
||||
}
|
||||
|
||||
@@ -212,11 +232,12 @@ void spi_lld_init(void) {
|
||||
void spi_lld_start(SPIDriver *spip) {
|
||||
|
||||
if (spip->state == SPI_STOP) {
|
||||
/* Clock activation.*/
|
||||
base_clock_enable(&spip->resources->base);
|
||||
branch_clock_enable(&spip->resources->branch_register_if);
|
||||
branch_clock_enable(&spip->resources->branch_peripheral);
|
||||
peripheral_reset(&spip->resources->reset);
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CCU1->CLK_M4_SSP0_CFG.RUN = 1;
|
||||
LPC_CGU->BASE_SSP0_CLK.PD = 0;
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicEnableVector(SSP0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP0_IRQ_PRIORITY));
|
||||
@@ -229,8 +250,6 @@ void spi_lld_start(SPIDriver *spip) {
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CCU1->CLK_M4_SSP1_CFG.RUN = 1;
|
||||
LPC_CGU->BASE_SSP1_CLK.PD = 0;
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicEnableVector(SSP1_IRQn,
|
||||
CORTEX_PRIORITY_MASK(LPC_SPI_SSP1_IRQ_PRIORITY));
|
||||
@@ -267,18 +286,44 @@ void spi_lld_stop(SPIDriver *spip) {
|
||||
spip->ssp->IMSC = 0;
|
||||
#if LPC_SPI_USE_SSP0
|
||||
if (&SPID1 == spip) {
|
||||
LPC_CGU->BASE_SSP0_CLK.PD = 1;
|
||||
LPC_CCU1->CLK_M4_SSP0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_SSP0_CFG.RUN = 0;
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicDisableVector(SSP0_IRQn);
|
||||
#endif
|
||||
#if defined(LPC43XX_M0)
|
||||
#if LPC_SPI_USE_SSP1
|
||||
/* Disable only if other SSP is stopped. */
|
||||
/* TODO: Won't work correctly if SSPs are split between cores! */
|
||||
if(SPID2.state == SPI_STOP) {
|
||||
#endif
|
||||
nvicDisableVector(SSP0_OR_SSP1_IRQn);
|
||||
#if LPC_SPI_USE_SSP1
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if LPC_SPI_USE_SSP1
|
||||
if (&SPID2 == spip) {
|
||||
LPC_CGU->BASE_SSP1_CLK.PD = 1;
|
||||
LPC_CCU1->CLK_M4_SSP1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_SSP1_CFG.RUN = 0;
|
||||
#if defined(LPC43XX_M4)
|
||||
nvicDisableVector(SSP1_IRQn);
|
||||
#endif
|
||||
#if defined(LPC43XX_M0)
|
||||
#if LPC_SPI_USE_SSP0
|
||||
/* Disable only if other SSP is stopped. */
|
||||
/* TODO: Won't work correctly if SSPs are split between cores! */
|
||||
if(SPID1.state == SPI_STOP) {
|
||||
#endif
|
||||
nvicDisableVector(SSP0_OR_SSP1_IRQn);
|
||||
#if LPC_SPI_USE_SSP1
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
peripheral_reset(&spip->resources->reset);
|
||||
branch_clock_disable(&spip->resources->branch_peripheral);
|
||||
branch_clock_disable(&spip->resources->branch_register_if);
|
||||
base_clock_disable(&spip->resources->base);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -220,6 +220,16 @@
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Structure used for SSP configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
base_clock_regs_t base;
|
||||
branch_clock_regs_t branch_register_if;
|
||||
branch_clock_regs_t branch_peripheral;
|
||||
peripheral_reset_t reset;
|
||||
} ssp_resources_t;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an SPI driver.
|
||||
*/
|
||||
@@ -296,6 +306,10 @@ struct SPIDriver {
|
||||
* @brief Pointer to the SSP registers block.
|
||||
*/
|
||||
LPC_SSPx_Type *ssp;
|
||||
/**
|
||||
* @brief Pointer to the non-peripheral SSP resources.
|
||||
*/
|
||||
const ssp_resources_t * resources;
|
||||
/**
|
||||
* @brief Number of bytes yet to be received.
|
||||
*/
|
||||
|
@@ -100,6 +100,9 @@ void systick_stop() {
|
||||
*/
|
||||
void hal_lld_init(void) {
|
||||
/* Initialize timer 3 to serve as a cycle (PCLK) counter. */
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_TIMER3_CFG.RUN = 1;
|
||||
while(!LPC_CCU1->CLK_M4_TIMER3_STAT.RUN);
|
||||
LPC_TIMER3->TCR = (1 << 1); /* CRST=1 */
|
||||
LPC_TIMER3->TCR = 0; /* CRST=0 */
|
||||
LPC_TIMER3->TC = 0;
|
||||
@@ -109,6 +112,9 @@ void hal_lld_init(void) {
|
||||
/* Initialize repetitive interrupt timer (RIT) to act like SysTick for
|
||||
* operating system process timing.
|
||||
*/
|
||||
LPC_CCU1->CLK_M4_RITIMER_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_M4_RITIMER_CFG.RUN = 1;
|
||||
while(!LPC_CCU1->CLK_M4_RITIMER_STAT.RUN);
|
||||
LPC_RITIMER->CTRL =
|
||||
(1 << 0) /* RITINT */
|
||||
| (1 << 1) /* RITENCLR */
|
||||
|
@@ -101,6 +101,7 @@ typedef enum IRQn {
|
||||
|
||||
#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */
|
||||
#include "lpc43xx.inc"
|
||||
#include "lpc43xx.h"
|
||||
|
||||
#endif /* __LPC43XX_M0_H */
|
||||
|
||||
|
@@ -8,6 +8,7 @@ set(PLATFORMSRC
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/sdc_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/serial_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/lpc43xx.c
|
||||
)
|
||||
|
||||
# Required include directories
|
||||
|
@@ -6,7 +6,8 @@ PLATFORMSRC = ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M0/hal_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/rtc_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/sdc_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/serial_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/lpc43xx.c
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M0 \
|
||||
|
@@ -122,6 +122,7 @@ typedef enum IRQn {
|
||||
|
||||
#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */
|
||||
#include "lpc43xx.inc"
|
||||
#include "lpc43xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
@@ -8,6 +8,7 @@ set(PLATFORMSRC
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/sdc_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/serial_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/lpc43xx.c
|
||||
)
|
||||
|
||||
# Required include directories
|
||||
|
@@ -6,7 +6,8 @@ PLATFORMSRC = ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M4/hal_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/rtc_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/sdc_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/serial_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/spi_lld.c \
|
||||
${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx/lpc43xx.c
|
||||
|
||||
# Required include directories
|
||||
PLATFORMINC = ${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M4 \
|
||||
|
Reference in New Issue
Block a user