LPCOpen v2.13 example project periph_sct will not work as written - Fixed code included

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPCOpen v2.13 example project periph_sct will not work as written - Fixed code included

2,199 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sun Dec 07 19:00:35 MST 2014
Firstly I want to say that I think the SCT is an awesome peripheral.  I intend to use it to replace processor intensive software bit-banged pattern generators in a few of my devices.  But I do have some concerns with the quality of some of the example programs that are provided in LPCOpen.

Example program periph_sct in LPCOpen v2.13 for the LPC824 will not work as written because there is setup code missing.  The SCT interrupt will never happen without first enabling a state for event 0, starting (unhalting) the SCT counter, and setting event 0 as the limit for the counter.

This is the working code, sct.c, with changes indicated in red:

/*
 * @brief State Configurable Timer (SCT) example
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2012
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include "board.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

#define TICKRATE_HZ (10)/* 10 ticks per second */

static volatile uint32_t ticks;

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @briefHandle interrupt from SysTick timer
 * @returnNothing
 */
void SysTick_Handler(void)
{
++ticks;
[color=#f00]//      Board_LED_Toggle(1);  // Get rid of this as it messes up the SCT_IRQHandler display[/color]
[/color]}

/**
 * @briefHandle interrupt from State Configurable Timer
 * @returnNothing
 */
void SCT_IRQHandler(void)
{
if (ticks % 2) {
Board_LED_Toggle(2);
}
else {
Board_LED_Toggle(0);
}

[color=#f00]/* Clear the SCT Event 0 Interrupt */[/color]
Chip_SCT_ClearEventFlag(LPC_SCT, SCT_EVT_0);
}

/**
 * @briefApplication main program
 * @returnNothing (This function will not return)
 */
int main(void)
{
[color=#f00]uint8_t result;

[/color]/* Generic Initialization */

 SystemCoreClockUpdate();
Board_Init();

[color=#f00]/* Enable SysTick Timer */  // Check that we are passing a valid value, endless loop if not
result = SysTick_Config(SystemCoreClock / TICKRATE_HZ);
while (result == 1);  // error - reload value not possible
[/color]
/* Custom Initialization */

[color=#f00]/* Initialize the SCT clock and reset the SCT */
//Chip_SCT_Init(LPC_SCT);  // Get rid of this call, use the inline functions within the call
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SCT);
Chip_SYSCTL_PeriphReset(RESET_SCT);
[/color]
/* Configure the SCT counter as a unified (32 bit) counter using the bus clock */
Chip_SCT_Config(LPC_SCT, SCT_CONFIG_32BIT_COUNTER | SCT_CONFIG_CLKMODE_BUSCLK);

[color=#f00]/* The match/capture REGMODE defaults to match mode */
/* No REGMODE changes are needed for this program   */
[/color]
/* Set the match count for match register 0 */
Chip_SCT_SetMatchCount(LPC_SCT, SCT_MATCH_0, SystemCoreClock / TICKRATE_HZ);

[color=#f00]/* Set the match reload value for match reload register 0*/[/color]
Chip_SCT_SetMatchReload(LPC_SCT, SCT_MATCH_0, SystemCoreClock / TICKRATE_HZ);

[color=#f00]/* Event 0 only happens on a match condition */
LPC_SCT->EVENT[0].CTRL = (1 << 12);

/* Event 0 only happens in state 0 */
LPC_SCT->EVENT[0].STATE = 0x00000001;

/* Event 0 is used as the counter limit */
LPC_SCT->LIMIT = 0x00000001;

/* Enable flag to request an interrupt for Event 0 */
[/color]Chip_SCT_EnableEventInt(LPC_SCT, SCT_EVT_0);

[color=#f00]/* Enable the interrupt for the SCT */
[/color]NVIC_EnableIRQ(SCT_IRQn);

[color=#f00]/* Start the SCT counter by clearing Halt_L in the SCT control register */
Chip_SCT_ClearControl(LPC_SCT, SCT_CTRL_HALT_L);

[/color]while (1) {
[color=#f00]//              Board_LED_Toggle(0);  // Get rid of this as it messes up the SCT_IRQHandler display
[/color]__WFI();
}

return 0;
}

Original Attachment has been moved to: sct_2.c.zip

标签 (1)
0 项奖励
回复
10 回复数

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by JoelEkstein on Tue Jan 26 06:26:44 MST 2016
Not worrying on any warranty now. Thanks for this advice.
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by acv on Fri Jan 09 11:35:02 MST 2015
NXP just released an update to the 824 that has the SCT update.

ACV
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Dec 11 21:36:57 MST 2014
I like the good news, and as far as the bad news goes, I did say "in the next releases".  I'm sure LPCOpen will continue to get better.

Thanks,
Larry
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Support on Thu Dec 11 16:22:00 MST 2014
Hi Larry,

Good news and not so good...;-)
An LPCOpen update for the LPC8xx family is about to be released. (that is the good news)
Unfortunately your recommendations are not completely addressed in this release (the not so good news).

The SCT examples were fixed. 
We usually do have a comprehensive set of register defines but, as you have pointed out, the SCT support was not as comprehensive as it should have been.
Same problem caused the mis-match of names (which has occurred other times as well due to late changes by the documentation folks).  

Best regards,
-NXP Support
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Dec 11 13:21:13 MST 2014
Thank you NXP_Support.  Really looking forward to seeing the improvements in the next releases.

LPCOpen has for the most part been getting much better, although I still prefer to use direct writes to the hardware registers.  Makes for lean and mean code.  Using the inline functions achieves pretty much the same result though and I can use them as they do simplify the coding quite a bit.  Pun intended.
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Support on Thu Dec 11 09:11:00 MST 2014
Hi Larry,

Thank you for your very good feedback.  I will try to coordinate the feedback with the code authors.  We run into some of these problems due to needing to use register names before the documentation is ready.  I have logged your feedback for the SW teams - it will be picked up in the next release cycle. 

Best regards,
-NXP Support
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue Dec 09 17:54:11 MST 2014
I would like to add that I think that the cst_8xx.h file should use register names that are in sync with the register names in the user manual.  For example, there is the use of EVn and the use of Event for the EVn registers.

#define SCT_EVn_STATE_RESERVED          (~3)
#define SCT_EVn_CTRL_RESERVED           (0xff800000)


uint16_t RESERVED8[32 - CONFIG_SCT_nRG];/*!< ...-0x2FE reserved */
__IO struct {/*!< 0x300-0x3FC  SCTEVENT.STATE / SCTEVENT.CTRL*/
uint32_t STATE;/*!< Event State Register */
uint32_t CTRL;/*!< Event Control Register */
} EVENT[CONFIG_SCT_nEV];


Consistency would make things a bit easier for us developers.

This has been brought up before in an earlier post, over a year ago, that was answered by NXP_Paul, concerning the header file used in the SCT Cookbook.

If you can't change the user manuals, then is there any chance of getting the SCT header files fixed?  You really should fix one or the other.
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue Dec 09 11:50:39 MST 2014
NXP, It would be nice to see a more comprehensive set of register defines and inline functions for setting up the SCT registers in LPCOpen v2.13 project lpc_chip_82x  file sct_8xx.h.  I find it a bit sparse and lacking in detail, though I did write my own inline functions and accompanying enums for setting the event state and event control registers.  I followed the format of sct_8xx.h and added these to an include file sct.h in my workspace.  By no means is this perfect, but it gives you an idea as to what I am asking for.

File sct.h:

enum states {STATE0, STATE1, STATE2, STATE3, STATE4, STATE5, STATE6, STATE7};
enum combmode {OR, MATCH, IO, AND};

/**
 * SCT Event State register values enum
 */
typedef enum CHIP_SCT_EVENT_STATE {
SCT_EVENT_STATE0 = 0,/*!< SCT Event State register 0 */
SCT_EVENT_STATE1 = 1,/*!< SCT Event State register 1 */
SCT_EVENT_STATE2 = 2,/*!< SCT Event State register 2 */
SCT_EVENT_STATE3 = 3,/*!< SCT Event State register 3 */
SCT_EVENT_STATE4 = 4,/*!< SCT Event State register 4 */
SCT_EVENT_STATE5 = 5,/*!< SCT Event State register 5 */
SCT_EVENT_STATE6 = 6,/*!< SCT Event State register 6 */
SCT_EVENT_STATE7 = 7,/*!< SCT Event State register 7 */
} CHIP_SCT_EVENT_STATE_T;

/**
 * @briefSet event states in the State Configurable Timer
 * @parampSCT: The base of SCT peripheral on the chip
 * @paramn: Event state register
 * @paramvalue: single or ORed state values
 * @returnNothing
 */
STATIC INLINE void Chip_SCT_SetEventState(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_STATE_T n, uint32_t value)
{
pSCT->EVENT[n].STATE = value;
}

/**
 * SCT Event Control register values enum
 */
typedef enum CHIP_SCT_EVENT_CTRL {
SCT_EVENT_CTRL0 = 0,/*!< SCT Event Control register 0 */
SCT_EVENT_CTRL1 = 1,/*!< SCT Event Control register 1 */
SCT_EVENT_CTRL2 = 2,/*!< SCT Event Control register 2 */
SCT_EVENT_CTRL3 = 3,/*!< SCT Event Control register 3 */
SCT_EVENT_CTRL4 = 4,/*!< SCT Event Control register 4 */
SCT_EVENT_CTRL5 = 5,/*!< SCT Event Control register 5 */
SCT_EVENT_CTRL6 = 6,/*!< SCT Event Control register 6 */
SCT_EVENT_CTRL7 = 7,/*!< SCT Event Control register 7 */
} CHIP_SCT_EVENT_CTRL_T;

/*
 * @brief Macro defines for SCT event control register
 */
#define SCT_EVENT_CTRL_CTRL_MATCHSEL(x)     (((x) & 0x0F) << 0)     /*!< Select match register */
#define SCT_EVENT_CTRL_HEVENT(x)            (((x) & 0x01) << 4)     /*!< Select L/H counter */
#define SCT_EVENT_CTRL_OUTSEL(x)            (((x) & 0x01) << 5)     /*!< Input/output select  */
#define SCT_EVENT_CTRL_IOSEL(x)             (((x) & 0x0F) << 6)     /*!< Select I/O signal number */
#define SCT_EVENT_CTRL_IOCOND(x)            (((x) & 0x03) << 10)    /*!< Select I/O condition */
#define SCT_EVENT_CTRL_COMBMODE(x)          (((x) & 0x03) << 12)    /*!< Select match and/or I/O condition */
#define SCT_EVENT_CTRL_STATELD(x)           (((x) & 0x01) << 14)    /*!< Control how STATEV modifies the state */
#define SCT_EVENT_CTRL_STATELD(x)           (((x) & 0x01) << 14)    /*!< Control how STATEV modifies the state */
#define SCT_EVENT_CTRL_MATCHMEM             (1 << 20)               /*!< MATCHMEM */
#define SCT_EVENT_CTRL_DIRECTION(x)         (((x) & 0x03) << 21)    /*!< Direction qualifier for event generation */

#define SCT_STATE(x)    (1 << ((x) & 0XFF))

/**
 * @briefSet event control values in the State Configurable Timer
 * @parampSCT: The base of SCT peripheral on the chip
 * @paramn: Event control register
 * @paramvalue: single or ORed control values
 * @returnNothing
 */
STATIC INLINE void Chip_SCT_SetEventControl(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_CTRL_T n, uint32_t value)
{
pSCT->EVENT[n].CTRL = value;
}



Those functions are called in the following manner:

/* Event 0 only happens in state 0 */
Chip_SCT_SetEventState(LPC_SCT, SCT_EVENT_STATE0, SCT_STATE(STATE0));

/* Event 0 only happens on a match condition */
Chip_SCT_SetEventControl(LPC_SCT, SCT_EVENT_CTRL0, SCT_EVENT_CTRL_COMBMODE(MATCH));



0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue Dec 09 11:13:22 MST 2014
Of course you can also omit the extra write to the SCT limit event register

/* Event 0 is used as the counter limit */
LPC_SCT->LIMIT = 0x00000001;


by setting auto limit in the SCT configuration register

/* Configure the SCT counter as a unified (32 bit) counter using the bus clock and auto limit */
Chip_SCT_Config(LPC_SCT, SCT_CONFIG_32BIT_COUNTER | SCT_CONFIG_CLKMODE_BUSCLK | SCT_CONFIG_AUTOLIMIT_L);
0 项奖励
回复

2,089 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Mon Dec 08 21:58:05 MST 2014
UPDATE: I have updated the code above as it was missing this

/* Event 0 is used as the counter limit */
LPC_SCT->LIMIT = 0x00000001;


The code now functions as it should.

0 项奖励
回复