This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2538: The MAC timer time period and overflow period cannot be set.

Part Number: CC2538
Other Parts Discussed in Thread: TIMAC, Z-STACK, ,

Hi, 

I am trying to set up the MAC timer for the CSMA algorithm.

I want to set the time period to 32,which is 31.25ns*32=1us, and the overflow period should be set to 320 to achieve 320us(backoff period required in 802.15.4 standard).

the problem is: after settting the time and overflow period, I read back those values from registers, but they are not the value I expected. the following is the value that I read back:

overflow period[1]
time period:[0]
timer value[0]
overflow value[1]

as we can see, the period values are just the same as the initial value a set for the counter and overflow counter.

also, the program will never hop to the mac timer interrupt.

here is my code:

void mac_timer_debug(void){
	mac_timer_disable();
	mac_timer_IRQ_disable();
	mac_timer_sync_disable();
	mac_timer_latch_mode(FULL_LATCH);
	mac_timer_set_time_period(0x20);//1us
	mac_timer_set_overflow_period(0x140);//320us
	mac_timer_set_count_value(0x0000);
	mac_timer_set_overflow(0x000001);
	mac_timer_IRQ_flag_clear();
	mac_timer_IRQ_maskon(RFCORE_SFR_MTIRQM_MACTIMER_OVF_PERM);
	mac_timer_IRQ_enable();
	printf("overflow period[%x]\n",mac_timer_read_overflow_period());
	printf("time period:[%x]\n",mac_timer_read_time_period());
	printf("timer value[%x]\n",mac_timer_get_count_value());
	printf("overflow value[%x]\n",mac_timer_get_overflow());
	mac_timer_enable();
}

PROCESS(mactimer_process, "csma process");
AUTOSTART_PROCESSES(&mactimer_process);
PROCESS_THREAD(mactimer_process, ev, data){
    PROCESS_BEGIN();

	mac_timer_debug();

	PROCESS_END();
}

Following is the MAC timer driver I create:

#define MTMSEL_MTOVF()			HWREG(RFCORE_SFR_MTMSEL)=0x00000000
#define MTMSEL_MTOVFPER()		do{\
									HWREG(RFCORE_SFR_MTMSEL)=(0x010<<RFCORE_SFR_MTMSEL_MTMOVFSEL_S);\
								}while(0)
#define MTMSEL_MTOVFCMP1()		do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMOVFSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x011<<RFCORE_SFR_MTMSEL_MTMOVFSEL_S;\
								}while(0)
#define MTMSEL_MTOVFCMP2()		do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMOVFSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x100<<RFCORE_SFR_MTMSEL_MTMOVFSEL_S;\
								}while(0)
#define MTMSEL_MTOVFCAP()		do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMOVFSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x001<<RFCORE_SFR_MTMSEL_MTMOVFSEL_S;\
								}while(0)
#define MTMSEL_MTTIM()			do{\
									HWREG(RFCORE_SFR_MTMSEL)=0x00000000;\
								}while(0)
#define MTMSEL_MTPER()			do{\
									HWREG(RFCORE_SFR_MTMSEL)=0x010;\
								}while(0)
#define MTMSEL_MTCMP1()			do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x011;\
								}while(0)
#define MTMSEL_MTCMP2()			do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x100;\
								}while(0)
#define MTMSEL_MTCAP()			do{\
									HWREG(RFCORE_SFR_MTMSEL)&=(~RFCORE_SFR_MTMSEL_MTMSEL_M);\
									HWREG(RFCORE_SFR_MTMSEL)|=0x001;\
								}while(0)
/*****************************************************************************
 * 函 数 名  : mac_timer_enable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 启动定时器
 * 输入参数  : 无
 * 输出参数  : 无
 * 返 回 值  : 无
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_enable(void){//启动mactimer计时器
	HWREG(RFCORE_SFR_MTCTRL)|=RFCORE_SFR_MTCTRL_RUN;
}

/*****************************************************************************
 * 函 数 名  : mac_timer_disable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 停止计时器
 * 输入参数  : 无
 * 输出参数  : 无
 * 返 回 值  : 无
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_disable(void){//停止计时器
	HWREG(RFCORE_SFR_MTCTRL)&=~RFCORE_SFR_MTCTRL_RUN;
}

/*****************************************************************************
 * 函 数 名  : mac_timer_sync_enable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 开启同步模式,计时器启动时会等到32kHz时钟的rising edge时才启动
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_sync_enable(void){
	HWREG(RFCORE_SFR_MTCTRL)|=RFCORE_SFR_MTCTRL_SYNC;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_sync_disable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 关闭同步模式,计时器启动时会立即启动
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_sync_disable(void){
	HWREG(RFCORE_SFR_MTCTRL)&=~RFCORE_SFR_MTCTRL_SYNC;
}




/*****************************************************************************
 * 函 数 名  : mac_timer_latch_mode
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 决定了在读取计时器数值时,是读取带overflow的时间戳,还是只读取计时器的数值
 * 输入参数  : LATCH_MODE mode: 可以为FULL_LATCH或HALF_LATCH
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_latch_mode(LATCH_MODE mode){
	if(mode==FULL_LATCH)HWREG(RFCORE_SFR_MTCTRL)|=RFCORE_SFR_MTCTRL_LATCH_MODE;
	else HWREG(RFCORE_SFR_MTCTRL)&=~RFCORE_SFR_MTCTRL_LATCH_MODE;
}


/*****************************************************************************
 * 函 数 名  : mac_timer_status
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 返回计时器当前状态
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  : 为0则为空闲,不为0则为运行中
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
uint8_t mac_timer_status(void){
	return HWREG(RFCORE_SFR_MTCTRL)&RFCORE_SFR_MTCTRL_STATE;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_set_count_value
 * 负 责 人  : 邹子豪
 * ���建日期  : 2021.2.23
 * 函数功能  : 设置计时器当前数值
 * 输入参数  : uint16_t value: 精度为31.25 ns
 * 输���参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_count_value(uint16_t value){
	mac_timer_disable();
	MTMSEL_MTTIM();
	HWREG(RFCORE_SFR_MTM0)=value&0xff;
	HWREG(RFCORE_SFR_MTM1)=value>>8;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_get_count_value
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 获取计时器当前数值
 * 输入参数  :
 * 输出参数  : uint16_t value: 精度为31.25 ns
 * 返 回 值  :
 * 调用关系  :
 * 其    它  : 注意: 获得的数据不包括溢出计数器的值,如需溢出计数器的数据,使用
mac_timer_get_overflow()
*****************************************************************************/
uint16_t mac_timer_get_count_value(void){
	uint16_t value;
	MTMSEL_MTTIM();
	value=HWREG(RFCORE_SFR_MTM0)&0xff;
	value|=(HWREG(RFCORE_SFR_MTM1)<<8)&0xff00;
	return value;
}


/*****************************************************************************
 * 函 数 名  : mac_timer_get_overflow
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 获取溢出计数器的数值
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  : overflow数值
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
uint32_t mac_timer_get_overflow(void){
	uint32_t ovf=0;
	MTMSEL_MTOVF();
	ovf=HWREG(RFCORE_SFR_MTMOVF0)&0xff;
	ovf|=(HWREG(RFCORE_SFR_MTMOVF1)<<8)&0xff00;
	ovf|=(HWREG(RFCORE_SFR_MTMOVF2)<<16)&0xff0000;
	return ovf;
}


/*****************************************************************************
 * 函 数 名  : mac_timer_set_overflow
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.23
 * 函数功能  : 设置overflow数值
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_overflow(uint32_t value){
	MTMSEL_MTOVF();
	HWREG(RFCORE_SFR_MTMOVF0)=value&0xff;
	HWREG(RFCORE_SFR_MTMOVF1)=(value>>8)&0xff;
	HWREG(RFCORE_SFR_MTMOVF2)=(value>>16)&0xff;
}

/*****************************************************************************
 * 函 数 名  : mac_timer_IRQ_maskon
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  : 打开相应的中断
 * 输入参数  : 可以为:
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_COMPARE2M
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_COMPARE1M
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_PERM
				RFCORE_SFR_MTIRQM_MACTIMER_COMPARE2M
				RFCORE_SFR_MTIRQM_MACTIMER_COMPARE1M
				RFCORE_SFR_MTIRQM_MACTIMER_PERM
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_IRQ_maskon(uint32_t mask){
	HWREG(RFCORE_SFR_MTIRQM)=mask;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_IRQ_maskoff
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  : 关闭相应中断
 * 输入参数  :
				可以为:
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_COMPARE2M
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_COMPARE1M
				RFCORE_SFR_MTIRQM_MACTIMER_OVF_PERM
				RFCORE_SFR_MTIRQM_MACTIMER_COMPARE2M
				RFCORE_SFR_MTIRQM_MACTIMER_COMPARE1M
				RFCORE_SFR_MTIRQM_MACTIMER_PERM
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_IRQ_maskoff(uint32_t mask){
	HWREG(RFCORE_SFR_MTIRQM)&=~mask;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_IRQ_flag_clear
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  : 归零所有中断标识
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_IRQ_flag_clear(void){
	HWREG(RFCORE_SFR_MTIRQF)=0;
}

/*****************************************************************************
 * 函 数 名  : mac_timer_IRQ_enable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  : 打开中断
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_IRQ_enable(void){
	IntEnable(INT_MACTIMR);
}

/*****************************************************************************
 * 函 数 名  : mac_timer_IRQ_disable
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  : 关闭中断
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_IRQ_disable(void){
	IntDisable(INT_MACTIMR);
}

/*****************************************************************************
 * 函 数 名  : mac_timer_set_time_period
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_time_period(uint16_t period){
	MTMSEL_MTPER();
	HWREG(RFCORE_SFR_MTM0)=period&0xff;
	HWREG(RFCORE_SFR_MTM1)=period>>8;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_set_overflow_period
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_overflow_period(uint32_t period){
	MTMSEL_MTOVFPER();
	HWREG(RFCORE_SFR_MTMOVF0)=period&0xff;
	HWREG(RFCORE_SFR_MTMOVF1)=(period>>8)&0xff;
	HWREG(RFCORE_SFR_MTMOVF2)=(period>>16)&0xff;
}

/*****************************************************************************
 * 函 数 名  : mac_timer_set_timer_compare
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_timer_compare(uint16_t cmp,MT_TIME_COMPARE which ){
	if(which==MT_TIME_COMPARE1) MTMSEL_MTCMP1();
	else MTMSEL_MTCMP2();
	HWREG(RFCORE_SFR_MTM0)=cmp&0xff;
	HWREG(RFCORE_SFR_MTM1)=cmp>>8;
}


/*****************************************************************************
 * 函 数 名  : mac_timer_set_overflow_compare
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
void mac_timer_set_overflow_compare(uint32_t cmp, MT_OVF_COMPARE which){
	if(which==MT_OVF_COMPARE1) MTMSEL_MTOVFCMP1();
	else MTMSEL_MTOVFCMP2();
	HWREG(RFCORE_SFR_MTMOVF0)=cmp&0xff;
	HWREG(RFCORE_SFR_MTMOVF1)=(cmp>>8)&0xff;
	HWREG(RFCORE_SFR_MTMOVF2)=(cmp>>16)&0xff;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_read_time_capture
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
uint16_t mac_timer_read_time_capture(void){
	uint16_t value;
	MTMSEL_MTCAP();
	value=HWREG(RFCORE_SFR_MTM0)&0xff;
	value|=(HWREG(RFCORE_SFR_MTM1)<<8)&0xff00;
	return value;
}
/*****************************************************************************
 * 函 数 名  : mac_timer_read_overflow_capture
 * 负 责 人  : 邹子豪
 * 创建日期  : 2021.2.24
 * 函数功能  :
 * 输入参数  :
 * 输出参数  :
 * 返 回 值  :
 * 调用关系  :
 * 其    它  :
*****************************************************************************/
uint32_t mac_timer_read_overflow_capture(void){
	uint32_t value;
	MTMSEL_MTOVFCAP();
	value=HWREG(RFCORE_SFR_MTMOVF0)&0xff;
	value|=(HWREG(RFCORE_SFR_MTMOVF1)<<8)&0xff00;
	value|=(HWREG(RFCORE_SFR_MTMOVF2)<<16)&0xff0000;
	return value;
}


uint32_t mac_timer_read_overflow_period(void){
	uint32_t value;
	MTMSEL_MTOVFPER();
	value=HWREG(RFCORE_SFR_MTMOVF0)&0xff;
	value|=(HWREG(RFCORE_SFR_MTMOVF1)<<8)&0xff00;
	value|=(HWREG(RFCORE_SFR_MTMOVF2)<<16)&0xff0000;
	return value;
}
uint16_t mac_timer_read_time_period(void){
	uint16_t value;
	MTMSEL_MTPER();
	value=HWREG(RFCORE_SFR_MTM0)&0xff;
	value|=(HWREG(RFCORE_SFR_MTM1)<<8)&0xff00;
	return value;
}

void MacTimerIntHandler(void){
	printf("timer:[%x]\n",mac_timer_get_count_value());
	printf("overflow:[%x]\n",mac_timer_get_overflow());
	mac_timer_IRQ_flag_clear();

}

  • Part Number: CC2538

    Hi,

    I am trying to set up the gp timer B as a high solution time recorder.

     I want to use the prescaler to enable the timer ticks every 1 us. 

    I will paste my code first and list all my problems below.

    /******************************************************************************
    *  Filename:       periodic_prescaler_16bit.c
    *  Revised:        $Date: 2013-04-10 11:03:42 +0200 (Wed, 10 Apr 2013) $
    *  Revision:       $Revision: 9699 $
    *
    *  Description:    Example demonstrating a periodic 16-bit timer with a clock 
    *                  prescaler.
    *
    *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
    *
    *
    *  Redistribution and use in source and binary forms, with or without
    *  modification, are permitted provided that the following conditions
    *  are met:
    *
    *    Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    *
    *    Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    *
    *    Neither the name of Texas Instruments Incorporated nor the names of
    *    its contributors may be used to endorse or promote products derived
    *    from this software without specific prior written permission.
    *
    *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    ******************************************************************************/
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "hw_ints.h"
    #include "hw_memmap.h"
    #include "gpio.h"
    #include "interrupt.h"
    #include "ioc.h"
    #include "hw_ioc.h"
    #include "sys_ctrl.h"
    #include "gptimer.h"
    #include "uartstdio.h"
    
    //
    // NOTE:
    // This example has been run on a SmartRF06 evaluation board.  Using a UART
    // window, watch the interrupt counter displayed on the consle.  This counter
    // displays how many periodic interrupts have been received.  Once this counter
    // is equal to the predefined NUMBER_OF_INTS, the counter should stop and the
    // TIMER0B interrupt should be disabled.
    //
    //*****************************************************************************
    //
    //! \addtogroup timer_examples_list
    //! <h1>16-Bit Periodic Timer using Prescaler (periodic_prescaler_16bit)</h1>
    //!
    //! This example shows how to configure Timer0B as a periodic timer with 
    //! a clock prescaller of X.  This will allow us to configure the interrupt to
    //! trigger every 1 second.  After NUMBER_OF_INTS interrupts, the Timer0B
    //! interrupt will be disabled.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - TIMER0 peripheral
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of
    //! Timer0B.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers. 
    //! - INT_TIMER0B - Timer0BIntHandler
    //
    //*****************************************************************************
    
    #define EXAMPLE_PIN_UART_RXD            GPIO_PIN_0 
    #define EXAMPLE_PIN_UART_TXD            GPIO_PIN_1 
    #define EXAMPLE_GPIO_UART_BASE          GPIO_A_BASE
    
    #define SYS_CTRL_32MHZ               32000000
    #define SYS_CTRL_16MHZ               16000000
    #define SYS_CTRL_8MHZ                 8000000
    #define SYS_CTRL_4MHZ                 4000000
    #define SYS_CTRL_2MHZ                 2000000
    #define SYS_CTRL_1MHZ                 1000000
    #define SYS_CTRL_500KHZ                500000
    #define SYS_CTRL_250KHZ                250000
    #define SYS_CTRL_62500HZ                62500
    
    //*****************************************************************************
    //
    // Number of interrupts before the timer gets turned off.
    //
    //*****************************************************************************
    #define NUMBER_OF_INTS          10
    
    //*****************************************************************************
    //
    // Counter to count the number of interrupts that have been called.
    //
    //*****************************************************************************
    static volatile uint32_t g_ui32Counter;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Map UART signals to the correct GPIO pins and configure them as
        // hardware controlled.
        //
        IOCPinConfigPeriphOutput(EXAMPLE_GPIO_UART_BASE, EXAMPLE_PIN_UART_TXD, 
                                 IOC_MUX_OUT_SEL_UART0_TXD);
        GPIOPinTypeUARTOutput(EXAMPLE_GPIO_UART_BASE, EXAMPLE_PIN_UART_TXD);
        
        IOCPinConfigPeriphInput(EXAMPLE_GPIO_UART_BASE, EXAMPLE_PIN_UART_RXD, 
                                IOC_UARTRXD_UART0);
        GPIOPinTypeUARTInput(EXAMPLE_GPIO_UART_BASE, EXAMPLE_PIN_UART_RXD);
         
        //
        // Initialize the UART (UART0) for console I/O.
        //
        UARTStdioInit(0);
    }
    
    uint32_t g_start = 0, i = 0;
    uint32_t g_end[NUMBER_OF_INTS] = {0};
    
    //*****************************************************************************
    //
    // The interrupt handler for the for Timer0B interrupt.
    //
    //*****************************************************************************
    void
    Timer0BIntHandler(void)
    {
        g_end[g_ui32Counter] = TimerValueGet(GPTIMER0_BASE, GPTIMER_B);
    
        //
        // Clear the timer interrupt flag.
        //
        TimerIntClear(GPTIMER0_BASE, GPTIMER_TIMB_TIMEOUT);  
    
        //
        // Update the periodic interrupt counter.
        //
        g_ui32Counter++;
    
        //
        // Print the periodic interrupt counter.
        //
        UARTprintf("Number of interrupts: %d\r", g_ui32Counter);
    
        //
        // Once NUMBER_OF_INTS interrupts have been received, turn off the
        // GPTimer0B interrupt.
        //
        if(g_ui32Counter == NUMBER_OF_INTS)
        {
            //
            // Disable the GPTimer0B interrupt.
            //
            IntDisable(INT_TIMER0B);
    
            //
            // Turn off GPTimer0B interrupt.
            //    
            TimerIntDisable(GPTIMER0_BASE, GPTIMER_TIMB_TIMEOUT);       
    
            //
            // Clear any pending interrupt flag.
            //
            TimerIntClear(GPTIMER0_BASE, GPTIMER_TIMB_TIMEOUT);         
    
      //      UARTprintf("\ng_start[%d]\n", g_start);
      //      for (i = 0; i < NUMBER_OF_INTS; i ++) {
      //          UARTprintf("g_end[%d] = %d\n", i, g_end[i]);
      //      }
            
            //
            // Indicate that NUMBER_OF_INTS have been received.
            //
            UARTprintf("\n\n%d interrupts received!", NUMBER_OF_INTS);
            UARTprintf("\nTimer0B is now disabled.");
        }	 
    }
    
    //*****************************************************************************
    //
    // Configure GPTimer0B as a 16-bit periodic counter with a clcok prescaller. 
    // GPTimer0B will be set to interrupt every second.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Initialize the interrupt counter.
        //
        g_ui32Counter = 0;
      
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // (no ext 32k osc, no internal osc)
        //
        SysCtrlClockSet(false, false, SYS_CTRL_SYSDIV_32MHZ);
    
        //
        // Set IO clock to the same as system clock
        //
        SysCtrlIOClockSet(SYS_CTRL_SYSDIV_32MHZ);    
        
        //
        // The Timer0 peripheral must be enabled for use.
        //
        SysCtrlPeripheralEnable(SYS_CTRL_PERIPH_GPT0);    
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for Timer operation.
        //
        InitConsole();   
    
        //
        // Display the example setup on the console.
        //
        UARTprintf("16-Bit Timer Interrupt ->");
        UARTprintf("\n   Timer = Timer0B");
        UARTprintf("\n   Mode = Periodic a with timer clock prescaller of 255");
        UARTprintf("\n   Number of interrupts = %d", NUMBER_OF_INTS);
        UARTprintf("\n   Rate = 1sec\n\n");
    
        //
        // Configure GPTimer0B as a 16-bit periodic timer.
        //
        TimerConfigure(GPTIMER0_BASE, GPTIMER_CFG_SPLIT_PAIR | 
                       GPTIMER_CFG_A_PERIODIC |GPTIMER_CFG_B_PERIODIC);
    
        //
        // Configure GPTimer0B clock prescaler for 255. This will make the 
        // effective timer clock be SYSCLOCK / 255.
        //
        TimerPrescaleSet(GPTIMER0_BASE, GPTIMER_B, 200); // 32MHz/200 = 160000Hz
    
        //
        // Set the GPTimer0B load value to 1sec by setting the timer load value 
        // to SYSCLOCK / 255. This is determined by:
        //      Prescaled clock = 16Mhz / 255
        //      Cycles to wait = 1sec * Prescaled clock
        //
        TimerLoadSet(GPTIMER0_BASE, GPTIMER_B, 160000);	// 1s	
    
        //
        // The following call will result in a dynamic interrupt table being used.
        // The table resides in RAM.
        // Alternatively SysTickIntHandler can be statically registred in your
        // application.
        // 
        TimerIntRegister(GPTIMER0_BASE, GPTIMER_B, Timer0BIntHandler);    
        
        //
        // Enable processor interrupts.
        //
        IntMasterEnable();     
    
        //
        // Configure the GPTimer0B interrupt for timer timeout.
        //    
        TimerIntEnable(GPTIMER0_BASE, GPTIMER_TIMB_TIMEOUT);    
    
        //
        // Enable the GPTimer0B interrupt on the processor (NVIC).
        //
        IntEnable(INT_TIMER0B);
    
        g_start = TimerValueGet(GPTIMER0_BASE, GPTIMER_B);
        
        //
        // Enable GPTimer0B.
        //
        TimerEnable(GPTIMER0_BASE, GPTIMER_B);    
    
        //
        // Loop forever while the Timer0B runs.
        //
        while(1)
        {
        }
    }
    

    Here are my problems:

    1: 

    In function "TimerLoadSet(GPTIMER0_BASE, GPTIMER_B, tValue)", no matter how I change the value of the third parameter "tValue"(larger or smaller), the timeout period will eventually shorten.

    2: 

    before enable the timer B, I read the timer value with function " start = TimerValueGet(GPTIMER0_BASE, GPTIMER_B)". However, when entering the timer B interrupt, I read the value again, which shows that the value is just 1 unit smaller than before starting. I thought the value should be 0.

  • Hi Zihao,

    I've merged your two recent posts as they both involved CC2538 timer operations.  Are you referencing the CC2538-SW, TIMAC, or Z-Stack solution?  I'm confident that you should reference a MAC solution for your MAC timer implementation.  You could then add your general purpose timer accordingly.  Each software download has a documentation folder that you can further review alongside the TRM.  You should be able to achieve a resolution of 1 us but I don't fully understand the questions you've given.  Periodic mode restarts timer counting automatically and will not change frequency so long as the timeout value remains constant.

    Regards,
    Ryan