Other Parts Discussed in Thread: SEGGER
Tool/software: Code Composer Studio
Hello,
My application is supposed to implement a velocity measurement by counting the amount of clock ticks elapsing between pulses coming in from a linear encoder (1nm indications coming in at approximately 50 000Hz). The way I do this is to configure the timer for input edge time mode where the timer reacts for every positive edge of the encoder pulses coming in at CCP1 and saves a snapshot value of the GPTMTBV register to the GPTMTBR register, repeating this for every encoder pulse. At the same time the uDMA is configured to be triggered by the capture event in the timer to transfer the value of GPTMTBR to a memory array buffer that I have defined to save the encoder timings.
The problem I am having is that I see that the same integer value is repeated twice sometimes in my memory buffer, almost like the encoder pulses has come in twice before the clock has counted one cycle, which should be impossible with a 80MHz clock. Without knowing exactly what caused this I cannot know exactly how to handle the velocity measurement at this moment.
I am grateful for all help I can get. The code is included bellow:
#include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include "inc/hw_timer.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "driverlib/timer.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/interrupt.h" #include "m_wide_timer5.h" #include "driverlib/udma.h" #include "../m_interupt_priorities.h" uint8_t pui8DMAControlTable[1024]; //#define timerSource ((uint32_t *) WTIMER5_BASE + 0x04C) uint32_t pui32DestBuffer[DMATransferSize]; // DMATransferSize = 100 uint32_t numberOfTickPerIntervall; //using this timer to sample the velocity of the z-direction void wideTimer5IntClear(void) { TimerIntClear(WTIMER5_BASE, TIMER_TIMB_DMA); } void wideTimer5Int(void){ wideTimer5IntClear(); // wideTimer5Off(); memset(pui32DestBuffer, 0, sizeof(pui32DestBuffer)); uDMAChannelTransferSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,( (void *) (WTIMER5_BASE + TIMER_O_TBR)), pui32DestBuffer, DMATransferSize); uDMAChannelEnable(UDMA_CHANNEL_I2S0TX); //restarts the dma transfer } //***************************************************************************** // //Initiate timer // //***************************************************************************** // void wideTimer5Init(void (*pfnHandler)(void)) { numberOfTickPerIntervall = INT32_MAX; HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; HWREG(GPIO_PORTD_BASE + GPIO_O_CR) |= 0x80; HWREG(GPIO_PORTD_BASE + GPIO_O_AFSEL) &= ~0x80; HWREG(GPIO_PORTD_BASE + GPIO_O_DEN) |= 0x80; HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = 0; SysCtlPeripheralReset(SYSCTL_PERIPH_WTIMER5); SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER5); // enable the periphiral and pins for the timer while(!SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER5)) { } // TimerDisable(WTIMER5_BASE, TIMER_BOTH); GPIOPinConfigure(GPIO_PD7_WT5CCP1); GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_7); wideTimer5Off(); TimerConfigure(WTIMER5_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_ONE_SHOT | TIMER_CFG_B_CAP_TIME_UP)); TimerControlEvent(WTIMER5_BASE, TIMER_B, TIMER_EVENT_POS_EDGE); TimerLoadSet(WTIMER5_BASE, TIMER_A, numberOfTickPerIntervall); TimerLoadSet(WTIMER5_BASE, TIMER_B, numberOfTickPerIntervall); //*************************************************************************************************************************************** //configure the DMA to transfer data about the timing of the encoder ticks SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)) { } uDMAEnable(); TimerDMAEventSet(WTIMER5_BASE,TIMER_DMA_CAPEVENT_B); //sets the capture event to trigger a dma request uDMAChannelAssign(UDMA_CH29_WTIMER5B); // so that the dma recieves data from wtimer5 uDMAControlBaseSet(pui8DMAControlTable); uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX, UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_ARB_1); uDMAChannelTransferSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC,( (void *) (WTIMER5_BASE + TIMER_O_TBR)), pui32DestBuffer, DMATransferSize); //Interrupt to restart the counting when the buffer has filled up wideTimer5IntClear(); TimerIntRegister(WTIMER5_BASE, TIMER_B, pfnHandler); IntPrioritySet(INT_WTIMER5B, INT_PRIO_WTIMER5); // enable everything TimerIntEnable(WTIMER5_BASE,TIMER_TIMB_DMA); TimerEnable(WTIMER5_BASE, TIMER_BOTH); uDMAChannelAssign(UDMA_CH29_WTIMER5B); // so that the dma recieves data from wtimer5 uDMAChannelEnable(UDMA_CHANNEL_I2S0TX); // extern bool uDMAChannelIsEnabled(uint32_t ui32ChannelNum); } void wideTimer5On(void) { TimerEnable(WTIMER5_BASE, TIMER_B); } void wideTimer5Off(void) { TimerDisable(WTIMER5_BASE, TIMER_B); }