/******************************************************************************* * NXP Semiconductors * (c) Copyright 2016 NXP Semiconductors * ALL RIGHTS RESERVED. ******************************************************************************** Services performed by NXP in this matter are performed AS IS and without any warranty. CUSTOMER retains the final decision relative to the total design and functionality of the end product. NXP neither guarantees nor will be held liable by CUSTOMER for the success of this project. NXP DISCLAIMS ALL WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ON ANY HARDWARE, SOFTWARE ORE ADVISE SUPPLIED TO THE PROJECT BY NXP, AND OR NAY PRODUCT RESULTING FROM NXP SERVICES. IN NO EVENT SHALL NXP BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT. CUSTOMER agrees to hold NXP harmless against any and all claims demands or actions by anyone on account of any damage, or injury, whether commercial, contractual, or tortuous, rising directly or indirectly as a result of the advise or assistance supplied CUSTOMER in connection with product, services or goods supplied under this Agreement. ******************************************************************************** * File: main.c * Owner: Petr Stancik * Version: 1.0 * Date: Oct-19-2016 * Classification: General Business Information * Brief: The ADC trigger using PDB in back2back mode * DMA used to read ADC data registers ******************************************************************************** ******************************************************************************** * Detailed Description: * * This example shows how to use the back-to-back mode of the PDB to trigger * sequence of ADC channels conversion. 4 PDB channel pre-triggers/triggers are * generated upon single PDB SW trigger. The first trigger is started by the PDB, * no delay is used. Next 3 triggers start after corresponding acknowledgment is * received from ADC. * * DMA is configured to read the ADC result registers. * Within DMA major interrupt the new conversion scan is started via PDB SW request. * * Converted data is used to change color of the EVB led based on Trimmer position. * * ------------------------------------------------------------------------------ * Test HW: FRDM-S32K144 * MCU: PS32K144HFVLL 0N77P * Fsys: 160MHz * Debugger: S32DS * Target: internal_FLASH * ******************************************************************************** Revision History: 1.0 Oct-19-2016 Petr Stancik Initial Version *******************************************************************************/ /******************************************************************************* * Includes *******************************************************************************/ //#include "S32K144.h" /* include peripheral declarations S32K144 */ #include "device_registers.h" #include #include #include #include #include #include "FlexCAN.h" /******************************************************************************* * External objects *******************************************************************************/ /******************************************************************************* * Global variables *******************************************************************************/ static uint32_t result[4] __attribute__ ((aligned (32))); /******************************************************************************* * Local functions *******************************************************************************/ void GPIO_Init(void); void PDB_Init(void); void ADC_Init(void); void WDOG_Disable(void); void PDB_Init(void); void DMA_init(void); void DMAMUX_Init(void); void IRQs_Init(void); void DMA0_IRQHandler(void); /******************************************************************************* Function Name : GPIO_Init Engineer : Petr Stancik Date : Oct-2-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : Initialize LED pins Issues : NONE *******************************************************************************/ void GPIO_Init(void) { PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: Clock enabled */ PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTE */ PORTE->PCR[4] |= PORT_PCR_MUX(5); /* Port E4: MUX = ALT5, CAN0_RX */ PORTE->PCR[5] |= PORT_PCR_MUX(5); /* Port E5: MUX = ALT5, CAN0_TX */ PORTD->PCR[0] |= PORT_PCR_MUX(1); /* MUX=1: PTD15, ALT=1 as GPIO */ PORTD->PCR[15] |= PORT_PCR_MUX(1); /* MUX=1: PTD15, ALT=1 as GPIO */ PORTD->PCR[16] |= PORT_PCR_MUX(1); /* MUX=1: PTD15, ALT=1 as GPIO */ PTD->PDDR |= 1<<0 | /* Configure BLUE LED as an output */ 1<<15 | /* Configure RED LED as an output */ 1<<16; /* Configure GREEN LED as an output */ PTD->PSOR |= 1<<0 | /* Turn off BLUE */ 1<<15 | /* Turn off RED */ 1<<16; /* Turn off GREEN */ } /******************************************************************************* Function Name : PDB_Init (Programmable Delay Block) Engineer : Petr Stancik Date : Oct-2-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : Initialize PDB for back-to-back mode Issues : NONE *******************************************************************************/ void PDB_Init(void) { PCC->PCCn[PCC_PDB0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable PDB clock */ // PDB0->MOD = PDB_MOD_MOD(220); PDB0->SC = PDB_SC_PDBEIE_MASK | /* Enable Sequence error interrupt */ PDB_SC_PRESCALER(0) | /* PDB frequency is: PDB clock = (System Clock) / ((2^(PRESCALER)) * (MULT)) */ PDB_SC_MULT(0) | /* Selects PDB0_TRG_IN0 input */ PDB_SC_LDMOD(0)| /* Load mode 0: The internal registers are loaded with the values from their buffers immediately after 1 is written to SC[LDOK]. */ PDB_SC_TRGSEL(0b1111)|/*Software trigger*/ PDB_SC_CONT(1); /*Continuous mode*/ PDB0->CH[0].C1 = (PDB_C1_BB(0x02) /* BB = E0h: Back-to-back for pre-triggers 1 */ | PDB_C1_TOS(0x01) /* TOS = 10h: Pre-trigger 0 asserts with DLY match */ | PDB_C1_EN(0x03)); /* EN = F0h: Pre-triggers 0/1 enabled */ // PDB0->CH[0].DLY[0] = 0; // PDB0->CH[0].DLY[1] = 0; PDB0->SC |= PDB_SC_PDBEN_MASK | /* Enable PDB */ PDB_SC_LDOK_MASK; /* Load values for MOD, IDLY, CHnDLYm, and POyDLY registers */ PDB0->SC |= PDB_SC_SWTRIG_MASK |PDB_SC_LDOK_MASK; } /******************************************************************************* Function Name : ADC_Init Engineer : Petr Stancik Date : Oct-19-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : Initialize ADC for HW trigger mode Issues : NONE *******************************************************************************/ void ADC0_init_HWTrigger(char Channel0, char Channel1) { PCC->PCCn[PCC_ADC0_INDEX] &=~ PCC_PCCn_CGC_MASK; /* Disable clock to change PCS */ PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_PCS(6); /* PCS=1: Select SOSCDIV2 */ PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable bus clock in ADC */ /***** Calibrate ADC0 *****/ ADC0->SC3 = ADC_SC3_CAL_MASK /* CAL = 1: Start calibration sequence */ | ADC_SC3_AVGE_MASK /* AVGE = 1: Enable hardware average */ | ADC_SC3_AVGS(3); /* AVGS = 11b: 32 samples averaged */ /* Wait for completion */ while (((ADC0->SC1[0] & ADC_SC1_COCO_MASK) >> ADC_SC1_COCO_SHIFT) == 0); /*************************/ ADC0->CFG1 |= ADC_CFG1_ADICLK(0) | /* Only ALTCLK1 is available */ ADC_CFG1_ADIV(1) | /* the clock rate is (input clock)/4 */ ADC_CFG1_MODE(1); /* 0b00: 8-bit, 0b01: 12-bit, 0b10: 10-bit */ ADC0->CFG2 = ADC_CFG2_SMPLTS(2); ADC0->SC2 |= ADC_SC2_ADTRG(1) | /* Conversion Trigger: 0b0= SW , 0b1 = HW */ ADC_SC2_DMAEN(1); /* enable DMA trigger */ ADC0->SC1[0] = ADC_SC1_ADCH(Channel0); ADC0->SC1[1] = ADC_SC1_ADCH(Channel1); ADC0->SC3 = 0x00000000; /* CAL=0: Do not start calibration sequence */ /* ADCO=0: One conversion performed */ /* AVGE,AVGS=0: HW average function disabled */ } /******************************************************************************* Function Name : WDOG_Disable Engineer : Petr Stancik Date : Oct-2-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : Disable watchdog Issues : NONE *******************************************************************************/ void WDOG_Disable(void) { WDOG->CNT=0xD928C520; /*Unlock watchdog*/ WDOG->CS &= ~WDOG_CS_EN_MASK; /*Disable watchdog*/ } /******************************************************************************* Function Name : DMA_init Engineer : Petr Stancik Date : Oct-19-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : Transfer Control Descriptor 0 : HW start --> ADC to Memory Issues : NONE *******************************************************************************/ void DMA_init(void) { SIM->PLATCGC |= SIM_PLATCGC_CGCDMA_MASK; // Clock enabled for DMA0 DMA->TCD[0].CSR &= 0xFFFFFFFF ^ DMA_TCD_CSR_DONE_MASK; // Clear Channel Done flag DMA->TCD[0].SADDR = DMA_TCD_SADDR_SADDR(&(ADC0->R[0])); DMA->TCD[0].SOFF = DMA_TCD_SOFF_SOFF(4); // Source Offset DMA->TCD[0].ATTR = DMA_TCD_ATTR_SMOD(0) | // Source address modulo feature is disabled DMA_TCD_ATTR_SSIZE(2) | // Source data transfer size: 1: 16-bit, 2=32-bit DMA_TCD_ATTR_DMOD(0) | // Destination address modulo feature: 0=disabled, x= x power of 2 buffer[DMOD=4->buffer of 16bytes] DMA_TCD_ATTR_DSIZE(2); // Destination data transfer size: 1: 16-bit, 2=32-bit DMA->TCD[0].NBYTES.MLOFFNO = DMA_TCD_NBYTES_MLNO_NBYTES(4); // Minor Byte Transfer Count is 4-bytes DMA->TCD[0].SLAST = DMA_TCD_SLAST_SLAST(-16); // Last Source Address Adjustment is -16 DMA->TCD[0].DADDR = DMA_TCD_DADDR_DADDR(&(result[0])); // Destination Address of Buffer DMA->TCD[0].DOFF = DMA_TCD_DOFF_DOFF(4); // Destination Address Signed Offset is 4 DMA->TCD[0].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(4) // Current Major Iteration Count is 4 | DMA_TCD_CITER_ELINKNO_ELINK(0); // The channel-to-channel linking is disabled DMA->TCD[0].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(-16); // Destination last address adjustment is -16 DMA->TCD[0].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(4) | // Starting major iteration count is 4 DMA_TCD_BITER_ELINKNO_ELINK(0); // The minor channel-to-channel linking is disabled DMA->TCD[0].CSR = DMA_TCD_CSR_BWC(0) | // BWC=0: No eDMA engine stalls - full bandwidth DMA_TCD_CSR_MAJORELINK(0) | // The channel-to-channel linking is disabled DMA_TCD_CSR_MAJORLINKCH(0) | // channel 1 will be called from ch0 DMA_TCD_CSR_ESG(0) | // The current channel�fs TCD is normal format - No scatter/gather DMA_TCD_CSR_DREQ(0) | // The channel's ERQ bit is not affected DMA_TCD_CSR_INTHALF(0) | // The half-point interrupt is disabled DMA_TCD_CSR_INTMAJOR(1) | // The end-of-major loop interrupt is enabled DMA_TCD_CSR_START(0); // The channel is not explicitly started DMA->SERQ = 0; // enable DMA channel 0 HW trigger } /******************************************************************************* Function Name : DMAMUX_init Engineer : Petr Stancik Date : Oct-19-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : configure DMAMUX ch 0 for ADC trigger source Issues : NONE *******************************************************************************/ void DMAMUX_Init (void) { PCC->PCCn[PCC_DMAMUX_INDEX] |= PCC_PCCn_CGC_MASK; // CGC=1: Clock enabled for DMAMUX0 DMAMUX->CHCFG[0] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_SOURCE(42); // ADC0 COCO is the source of the DMA0 channel DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel } /******************************************************************************* Function Name : IRQs_Init Engineer : Petr Stancik Date : Oct-19-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : configure NVIC, enable DMA ch0 interrupt Issues : NONE *******************************************************************************/ void IRQs_Init (void) { S32_NVIC->ICPR[0] = 1 << (0 % 32); /* IRQ0-DMA ch0: clr any pending IRQ*/ S32_NVIC->ISER[0] = 1 << (0 % 32); /* IRQ0-DMA ch0: enable IRQ */ S32_NVIC->IP[0] = 0xA; /* IRQ0-DMA ch0: priority 10 of 0-15*/ } /******************************************************************************* Function Name : DMA0_IRQHandler Engineer : Petr Stancik Date : Oct-19-2016 Parameters : NONE Modifies : NONE Returns : NONE Notes : DMA ch0 interrupt routine Issues : NONE *******************************************************************************/ void DMA0_IRQHandler(void) { PDB0->SC |= PDB_SC_SWTRIG_MASK; /* restart PDB counter */ DMA->CINT = 0; // clear DMA channel 0 interrupt flag } void Clock_init_100MHz(void) { /* System clock initialization */ /* SOSC Configuration */ /* 8 MHz crystal */ SCG->SOSCDIV = 0x00010101u; /* SCG_SOSCDIV: SOSCDIV3=1, SOSCDIV2=1, SOSCDIV1=1 */ SCG->SOSCCFG = 0x00000034u; /* SCG_SOSCCFG: RANGE=3, EREFS=1 */ while(SCG->SOSCCSR & 0x00800000u); SCG->SOSCCSR= 0x5u; /* SCG_SOSCCSR: SOSCLPEN=1, SOSCEN=1 */ while(!(SCG->SOSCCSR & 0x01000000u)); /* SPLL Configuration 96 MHz */ SCG->SPLLDIV = 0x00010101u; /* SCG_SPLLDIV: SPLLDIV3=1, SPLLDIV2=1, SPLLDIV1=1 */ /* PREDIV = 0 8 MHz / 1 = 8 MHz */ /* MULT = 8 8 MHz / 1 * 24 = 192 MHz VCO */ /* SOURCE = 0 system OSC (8 MHz) */ SCG->SPLLCFG = 0x00090000; while(SCG->SPLLCSR & 0x00800000u); SCG->SPLLCSR=0x01; /* SCG_SPLLCSR: SPLLEN=1 */ while(!(SCG->SPLLCSR & 0x01000000u)); /* configure HSRUN mode */ /* DIVCORE = 0; CORE_CLK = 96 MHz */ /* DIVPLAT = 0; SYS_CLK = 96 MHz */ /* DIVBUS = 1; BUS_CLK = 48 MHz */ /* DIVSLOW = 3; FLASH_CLK = 24 MHz */ /* SCS = 6; pll clock source */ SCG->HCCR = 0x06000013; SMC->PMPROT = 0x80; /* Allow high speed run */ SMC->PMCTRL = 0x60; /* Switch to high speed run */ while(!(SMC->PMSTAT & 0x00000080u)); } /******************************************************************************* * Global functions *******************************************************************************/ #define max_indice 200 //indica la lunghezza del pacchetto CAN #define NUM_IDS 12 //Indica il numero di Identificativi salvati nei Buffer 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 //Dal Buffer 16 al Buffer 21 verranno salvati altri sei ID -> vedere FLEXCAN.c //Misure di tensione in mV uint32_t threshold_low = 2000; uint32_t threshold_high = 3000; uint32_t limite_inferiore_high = 2750; uint32_t limite_superiore_high = 3600; uint32_t limite_inferiore_low = 1400; uint32_t limite_superiore_low = 2250; uint32_t counter = 0; uint32_t *quanti_dominanti; uint32_t identifier_received; float time_core = 0.0000000125; //1/(80MHz) volatile bool ricezione_id = false; volatile bool salvo_dati = false; int i = 0; struct vettori_tensione { uint32_t Buffer_Low[max_indice]; uint32_t Buffer_High[max_indice]; uint32_t Buffer_High_dominante[max_indice]; uint32_t Buffer_Low_dominante[max_indice]; }; struct vettori_tensione vectors; int main(void) { WDOG_Disable(); Clock_init_100MHz(); GPIO_Init(); ADC0_init_HWTrigger(3,0); PDB_Init(); DMA_init(); DMAMUX_Init(); IRQs_Init(); FLEXCAN0_init(); PDB0->SC |= PDB_SC_SWTRIG_MASK; /* restart PDB counter */ for (;;) { // if (result[0] < 1638 && result[0]>0)/*|| result[1] < 1638 || result[2] < 1638 || result[3] < 1638 */ { for (i=0; iPSOR |= 1<PCOR |= 1<