/*Set up output clocks per bit for SSP bus*/ void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale) { uint32_t temp; temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF))); pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate)); pSSP->CPSR = prescale; }
/*********************************************************************//** * @brief Setup clock rate for SSP device * @param[in] SSPx SSP peripheral definition, should be: * - LPC_SSP0: SSP0 peripheral * - LPC_SSP1: SSP1 peripheral * @param[in] target_clock : clock of SSP (Hz) * @return None ***********************************************************************/ static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock) { uint32_t prescale, cr0_div, cmp_clk, ssp_clk; ssp_clk = CLKPWR_GetCLK (CLKPWR_CLKTYPE_PER); /* Find closest divider to get at or under the target frequency. Use smallest prescale possible and rely on the divider to get the closest target frequency */ cr0_div = 0; cmp_clk = 0xFFFFFFFF; prescale = 2; while (cmp_clk > target_clock) { cmp_clk = ssp_clk / ((cr0_div + 1) * prescale); if (cmp_clk > target_clock) { cr0_div++; if (cr0_div > 0xFF) { cr0_div = 0; prescale += 2; } } } /* Write computed prescaler and divider back to register */ SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK; SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK; SSPx->CPSR = prescale & SSP_CPSR_BITMASK; }
/********************************************************************//** * @brief Initializes the SSPx peripheral according to the specified * parameters in the SSP_ConfigStruct. * @param[in] SSPx SSP peripheral selected, should be: * - LPC_SSP0 :SSP0 peripheral * - LPC_SSP1 :SSP1 peripheral * @param[in] SSP_ConfigStruct Pointer to a SSP_CFG_Type structure that * contains the configuration information for the specified * SSP peripheral. * @return None *********************************************************************/ void SSP_Init(LPC_SSPn_Type *SSPx, SSP_CFG_Type *SSP_ConfigStruct) { uint32_t tmp; uint32_t prescale, cr0_div, cmp_clk; uint64_t ssp_clk; CHECK_PARAM(PARAM_SSPx(SSPx)); if(SSPx == LPC_SSP0) { /* Set up clock and power for SSP0 module */ //LPC_CGU->BASE_SSP0_CLK = (SRC_PL160M_0<<24) | (1<<11); CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_SSP0); } else if(SSPx == LPC_SSP1) { /* Set up clock and power for SSP1 module */ //LPC_CGU->BASE_SSP1_CLK = (SRC_PL160M_0<<24) | (1<<11); CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_SSP1); } else { return; } /* Configure SSP, interrupt is disable, LoopBack mode is disable, * SSP is disable, Slave output is disable as default */ tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \ | (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit)) & SSP_CR0_BITMASK; // write back to SSP control register SSPx->CR0 = tmp; tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK; // Write back to CR1 SSPx->CR1 = tmp; // Set clock rate for SSP peripheral if(SSPx == LPC_SSP0) ssp_clk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_SSP0); else ssp_clk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_SSP1); cr0_div = 0; cmp_clk = 0xFFFFFFFF; prescale = 2; while (cmp_clk > SSP_ConfigStruct->ClockRate) { cmp_clk = ssp_clk / ((cr0_div + 1) * prescale); if (cmp_clk > SSP_ConfigStruct->ClockRate) { cr0_div++; if (cr0_div > 0xFF) { cr0_div = 0; prescale += 2; } } } /* Write computed prescaler and divider back to register */ SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK; SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK; SSPx->CPSR = prescale & SSP_CPSR_BITMASK; }
/*********************************************************************** * * Function: ssp_set_clock * * Purpose: Sets or resets the serial clock rate of the SSP interface * (in Hz) * * Processing: * Determine the best dividers to generate the closest possible * target clock rate for the SSP. * * Parameters: * psspdrvdat : Pointer to driver data * target_clock : The value in Hz for the new SSP serial clock * * Outputs: None * * Returns: _ERROR if the configuration setup failed, otherwise _NO_ERROR * * Notes: None * **********************************************************************/ static STATUS ssp_set_clock(SSP_DRVDAT_T *psspdrvdat, UNS_32 target_clock) { UNS_32 control, prescale, cr0_div, cmp_clk, ssp_clk; /* The SSP clock is derived from the (main system oscillator / 2), so compute the best divider from that clock */ ssp_clk = clkpwr_get_clock_rate(sspclks [psspdrvdat->thisdev]); /* Find closest divider to get at or under the target frequency. Use smallest prescaler possible and rely on the divider to get the closest target frequency */ cr0_div = 0; cmp_clk = 0xFFFFFFFF; prescale = 2; while (cmp_clk > target_clock) { cmp_clk = ssp_clk / ((cr0_div + 1) * prescale); if (cmp_clk > target_clock) { cr0_div++; if (cr0_div > 0xFF) { cr0_div = 0; prescale += 2; } } } /* Write computed prescaler and divider back to register */ control = psspdrvdat->regptr->cr0 &= ~(SSP_CR0_SCR(0xFF)); psspdrvdat->regptr->cr0 = control | SSP_CR0_SCR(cr0_div - 1); psspdrvdat->regptr->cpsr = prescale; return _NO_ERROR; }
/********************************************************************//** * @brief Initializes the LPC_SSP0 peripheral according to the specified * parameters in the SSP_ConfigStruct. * @param[in] None * @return None *********************************************************************/ void SSP_Init(void) { uint32_t tmp; // initialize pinsel for SSP0 /* MISO0: P0.8 */ LPC_IOCON->PIO0_8 = PINSEL_PIO_FUNC(1) | PINSEL_PIO_MODE(2); /* MOSI0: P0.9 */ LPC_IOCON->PIO0_9 = PINSEL_PIO_FUNC(1) | PINSEL_PIO_MODE(2); /* P0.6 function 2 is SSP clock, need to combined with IOCONSCKLOC register setting */ LPC_IOCON->SCK_LOC = 0x02; LPC_IOCON->PIO0_6 = PINSEL_PIO_FUNC(2) | PINSEL_PIO_MODE(2); #if USE_CS LPC_IOCON->PIO0_2 &= ~0x1F; LPC_IOCON->PIO0_2 |= PINSEL_PIO_FUNC(1) | PINSEL_PIO_MODE(2); /* SSP SSEL */ #else /* Enable AHB clock to the GPIO domain. */ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); #endif /* Reset SSP0 peripheral */ LPC_SYSCON->PRESETCTRL |= (0x1<<0); /* Enable clock for SSP0 */ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); LPC_SYSCON->SSP0CLKDIV = 0x02; /* Configure SSP, interrupt is disable, LoopBack mode is disable, * SSP is disable, Slave output is disable as default */ tmp = ((SSP_CPHA_USED) | (SSP_CPOL_USED) \ | (SSP_FRAME_SPI) | (SSP_DATA_BIT_USED)) & SSP_CR0_BITMASK; // write back to SSP control register LPC_SSP0->CR0 = tmp; // Write back to CR1 LPC_SSP0->CR1 = SSP_MASTER_MODE; // Set clock rate for SSP peripheral LPC_SSP0->CR0 &= (~ SSP_CR0_SCR (0xFF)) & SSP_CR0_BITMASK; LPC_SSP0->CR0 |= (SSP_CR0_SCR(0x05)) & SSP_CR0_BITMASK; LPC_SSP0->CPSR = 0x02 & SSP_CPSR_BITMASK; // SSP Enable LPC_SSP0->CR1 |= SSP_CR1_SSP_EN; }
/*********************************************************************//** * @brief Setup clock rate for SSP device * @param[in] SSPx SSP peripheral definition, should be: * - LPC_SSP0: SSP0 peripheral * - LPC_SSP1: SSP1 peripheral * @param[in] target_clock : clock of SSP (Hz) * @return None ***********************************************************************/ static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock) { uint32_t prescale, cr0_div, cmp_clk, ssp_clk; CHECK_PARAM(PARAM_SSPx(SSPx)); /* The SSP clock is derived from the (main system oscillator / 2), so compute the best divider from that clock */ if (SSPx == LPC_SSP0){ ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP0); } else if (SSPx == LPC_SSP1) { ssp_clk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SSP1); } else { return; } /* Find closest divider to get at or under the target frequency. Use smallest prescale possible and rely on the divider to get the closest target frequency */ cr0_div = 0; cmp_clk = 0xFFFFFFFF; prescale = 2; while (cmp_clk > target_clock) { cmp_clk = ssp_clk / ((cr0_div + 1) * prescale); if (cmp_clk > target_clock) { cr0_div++; if (cr0_div > 0xFF) { cr0_div = 0; prescale += 2; } } } /* Write computed prescaler and divider back to register */ SSPx->CR0 &= (~SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK; SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK; SSPx->CPSR = prescale & SSP_CPSR_BITMASK; }
/*********************************************************************** * * Function: ssp_ioctl * * Purpose: SSP configuration block * * Processing: * This function is a large case block. Based on the passed function * and option values, set or get the appropriate SSP parameter. * * Parameters: * devid: Pointer to SSP config structure * cmd: ioctl command * arg: ioctl argument * * Outputs: None * * Returns: The status of the ioctl operation * * Notes: None * **********************************************************************/ STATUS ssp_ioctl(INT_32 devid, INT_32 cmd, INT_32 arg) { SSP_REGS_T *sspregs; SSP_CBS_T *psspcb; UNS_32 sspclk, tmp, tmp2; SSP_DRVDAT_T *sspdrvdat = (SSP_DRVDAT_T *) devid; STATUS status = _ERROR; if (sspdrvdat->init == TRUE) { status = _NO_ERROR; sspregs = sspdrvdat->regptr; switch (cmd) { case SSP_ENABLE: if (arg == 1) { /* Enable SSP */ sspregs->cr1 |= SSP_CR1_SSP_ENABLE; } else { /* Disable SSP */ sspregs->cr1 &= ~SSP_CR1_SSP_ENABLE; } break; case SSP_CONFIG: status = ssp_configure((SSP_CONFIG_T *) arg, sspdrvdat); break; case SSP_ENABLE_LOOPB: /* Enable or disable loopback mode */ if (arg == 1) { /* Enable SSP loopback mode */ sspregs->cr1 |= SSP_CR1_LBM; } else { /* Disable SSP loopback mode */ sspregs->cr1 &= ~SSP_CR1_LBM; } break; case SSP_SO_DISABLE: /* Slave output disable */ if (arg != 0) { sspregs->cr1 |= SSP_CR1_SOD; } else { sspregs->cr1 &= ~SSP_CR1_SOD; } break; case SSP_SET_CALLBACKS: psspcb = (SSP_CBS_T *) arg; sspdrvdat->cbs.txcb = psspcb->txcb; sspdrvdat->cbs.rxcb = psspcb->rxcb; break; case SSP_CLEAR_INTS: sspregs->icr = ((UNS_32) arg) & (SSP_ICR_RORIC | SSP_ICR_RTIC); break; case SSP_GET_STATUS: /* Return an SSP status */ switch (arg) { case SSP_CLOCK_ST: /* Return clock speed of SSP interface */ tmp = (sspregs->cr0 & SSP_CR0_SCR(0xFF)) >> 8; tmp2 = sspregs->cpsr; if (tmp2 < 1) { /* Not a valid value, so use a divider of 1 */ tmp2 = 1; } /* Compute SSP bit clock rate */ sspclk = clkpwr_get_clock_rate( sspclks [sspdrvdat->thisdev]); status = sspclk / (tmp2 * (tmp + 1)); break; case SSP_PENDING_INTS_ST: status = sspregs->mis; break; case SSP_RAW_INTS_ST: status = sspregs->ris; break; default: /* Unsupported parameter */ status = LPC_BAD_PARAMS; break; } break; default: /* Unsupported parameter */ status = LPC_BAD_PARAMS; } }
/********************************************** ИНИЦИАЛИЗАЦИЯ СИСТЕМЫ ПРЕРЫВАНИЙ **********************************************/ void InitializeInterruptSystem() { /* Initialize interrupt system */ int_initialize(0xFFFFFFFF); /* Install standard IRQ dispatcher at ARM IRQ vector */ int_install_arm_vec_handler(IRQ_VEC, (PFV) lpc32xx_irq_handler); /* Install standard FIQ dispatcher at ARM IRQ vector */ int_install_arm_vec_handler(FIQ_VEC, (PFV) lpc32xx_fiq_handler); //---------------------HSTIMER------------------------------------ /* Install HSTIMER interrupt handler as a IRQ interrupts */ int_install_irq_handler(IRQ_HSTIMER, (PFV) hstimer_user_interrupt); // Save address of register block hst_regptr = HSTIMER; gpio_regptr = GPIO; // LEDs off //gpio_regptr->p3_outp_clr = LED1 | LED2; //gpio_regptr->p1_dir_set = LED3; // Enable timer system clock clkpwr_clk_en_dis(CLKPWR_HSTIMER_CLK, 1); // Disable high speed timer and match timers hst_regptr->hstim_ctrl = HSTIM_CTRL_RESET_COUNT; hst_regptr->hstim_mctrl = 0; hst_regptr->hstim_ctrl = 0; // Clear pending interrupts hst_regptr->hstim_int = (HSTIM_MATCH0_INT | HSTIM_MATCH1_INT | HSTIM_MATCH2_INT | HSTIM_GPI_06_INT | HSTIM_RTC_TICK_INT); hst_regptr->hstim_mctrl = HSTIM_CNTR_MCR_MTCH(0) | HSTIM_CNTR_MCR_RESET(0); hst_regptr->hstim_pmatch = 13-1; hst_regptr->hstim_match[0] = 1000;//1ms 000; hst_regptr->hstim_ctrl = HSTIM_CTRL_COUNT_ENAB;//start hstimer // Enable interrupt in the interrupt controller int_enable(IRQ_HSTIMER); //---------------------SSP1------------------------------------ ssp1_regptr = SSP1; // Pointer to SSP1 registers // Enable ssp1 system clock clkpwr_clk_en_dis(CLKPWR_SSP1_CLK, 1); //конфигурация IO gpio_regptr->p2_mux_clr = P2_GPIO04_SSEL1; gpio_regptr->p2_dir_set = P2_DIR_GPIO(4); gpio_regptr->p3_outp_set = P3_STATE_GPIO(4); /* The MISO, MOSI, and SCK signals are controlled by the SSP1 */ gpio_regptr->p_mux_set = (P_SPI2DATAIO_MOSI1 | P_SPI2DATAIN_MISO1 | P_SPI2CLK_SCK1); ssp1_regptr->cpsr = SSP_CPSR_CPDVSR(16);//8);//4);//4);//prescale //ssp_clk / ((cr0_div + 1) * prescale); //prescale = 16; SCR = 4 - 1.25MGz ssp1_regptr->cr0 = SSP_CR0_DSS(8) |//data size 8 bit SSP_CR0_FRF_SPI |//Motorola SPI mode SSP_CR0_SCR(4);//serial clock rate // Default Master mode // Disable SSP1 ssp1_regptr->cr1 &= ~SSP_CR1_SSP_ENABLE; // interr handler SSP1 IRQ //int_install_irq_handler(IRQ_SSP1, (PFV) ssp1_user_interrupt); // Enable interrupt in the interrupt controller //int_enable(IRQ_SSP1); // Clear interrupt in the interrupt controller //int_clear(IRQ_SSP1); // Enable SSP1 ssp1_regptr->cr1 |= SSP_CR1_SSP_ENABLE; }//InitializeInterruptSystem()