1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

Partial PWM implementation for lpc17xx.

This commit is contained in:
James Snyder 2010-02-20 00:27:13 +00:00
parent a3eb58211d
commit b79ed03629
3 changed files with 50 additions and 74 deletions

View File

@ -46,6 +46,10 @@
/* TIMER ------------------------------- */
#define _TIM
/* PWM ------------------------------- */
#define _PWM 1
#define _PWM1 1
/************************** GLOBAL/PUBLIC MACRO DEFINITIONS *********************************/
#ifdef DEBUG

View File

@ -23,6 +23,7 @@
#include "lpc17xx_uart.h"
#include "lpc17xx_timer.h"
#include "lpc17xx_clkpwr.h"
#include "lpc17xx_pwm.h"
// ****************************************************************************
// Platform initialization
@ -325,93 +326,70 @@ void platform_cpu_disable_interrupts()
{
__disable_irq();
}
/*
// ****************************************************************************
// PWM functions
static const u32 pwm_tcr[] = { ( u32 )&PWM0TCR, ( u32 )&PWM1TCR };
static const u32 pwm_pr[] = { ( u32 )&PWM0PR, ( u32 )&PWM1PR };
static const u32 pwm_pc[] = { ( u32 )&PWM0PC, ( u32 )&PWM1PC };
static const u32 pwm_pcr[] = { ( u32 )&PWM0PCR, ( u32 )&PWM1PCR };
static const u32 pwm_mcr[] = { ( u32 )&PWM0MCR, ( u32 )&PWM1MCR };
static const u32 pwm_ler[] = { ( u32 )&PWM0LER, ( u32 )&PWM1LER };
static const u32 pwm_channels[ 2 ][ 6 ] =
{
{ ( u32 )&PWM0MR1, ( u32 )&PWM0MR2, ( u32 )&PWM0MR3, ( u32 )&PWM0MR4, ( u32 )&PWM0MR5, ( u32 )&PWM0MR6 },
{ ( u32 )&PWM1MR1, ( u32 )&PWM1MR2, ( u32 )&PWM1MR3, ( u32 )&PWM1MR4, ( u32 )&PWM1MR5, ( u32 )&PWM1MR6 },
};
// Timer register definitions
enum
{
PWM_ENABLE = 1,
PWM_RESET = 2,
PWM_MODE = 8,
PWM_ENABLE_1 = 1 << 9,
PWM_ENABLE_2 = 1 << 10,
PWM_ENABLE_3 = 1 << 11,
PWM_ENABLE_4 = 1 << 12,
PWM_ENABLE_5 = 1 << 13,
PWM_ENABLE_6 = 1 << 14,
};
// Helper function: get timer clock
static u32 platform_pwm_get_clock( unsigned id )
{
unsigned pwmid = id / 6;
PREG PWMxPR = ( PREG )pwm_pr[ pwmid ];
return Fpclk / ( *PWMxPR + 1 );
return CLKPWR_GetPCLK( CLKPWR_PCLKSEL_PWM1 ) / ( PWM1->PR + 1 );
}
// Helper function: set timer clock
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
{
u32 div = Fpclk / clock, prevtc;
unsigned pwmid = id / 6;
PREG PWMxPR = ( PREG )pwm_pr[ pwmid ];
PREG PWMxPC = ( PREG )pwm_pc[ pwmid ];
PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ];
PWM_TIMERCFG_Type PWMCfgDat;
prevtc = *PWMxTCR;
*PWMxTCR = 0;
*PWMxPC = 0;
*PWMxPR = div - 1;
*PWMxTCR = prevtc;
return Fpclk / div;
PWMCfgDat.PrescaleOption = PWM_TIMER_PRESCALE_USVAL;
PWMCfgDat.PrescaleValue = 1000000ULL / clock;
PWM_Init(PWM1, PWM_MODE_TIMER, &PWMCfgDat);
return clock;
}
// Setup all PWM channels
static void platform_setup_pwm()
{
unsigned i;
PREG temp;
PWM_TIMERCFG_Type PWMCfgDat;
PWM_MATCHCFG_Type PWMMatchCfgDat;
// Keep clock in reset, set PWM code
PWM_ResetCounter(PWM1);
// Set match mode (reset on MR0 match)
PWMMatchCfgDat.IntOnMatch = DISABLE;
PWMMatchCfgDat.MatchChannel = 0;
PWMMatchCfgDat.ResetOnMatch = ENABLE;
PWMMatchCfgDat.StopOnMatch = DISABLE;
PWM_ConfigMatch(PWM1, &PWMMatchCfgDat);
for( i = 0; i < 2; i ++ )
{
// Keep clock in reset, set PWM code
temp = ( PREG )pwm_tcr[ i ];
*temp = PWM_RESET;
// Set match mode (reset on MR0 match)
temp = ( PREG )pwm_mcr[ i ];
*temp = 0x02;
// Set base frequency to 1MHz
platform_pwm_set_clock( i * 6, 1000000 );
}
// Set base frequency to 1MHz
platform_pwm_set_clock( 0, 1000000 );
}
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
{
unsigned pwmid = id / 6, chid = id % 6;
PREG PWMxMR0 = pwmid == 0 ? ( PREG )&PWM0MR0 : ( PREG )&PWM1MR0;
PREG PWMxMRc = ( PREG )pwm_channels[ pwmid ][ chid ];
PREG PWMxLER = ( PREG )pwm_ler[ pwmid ];
u32 divisor;
divisor = platform_pwm_get_clock( id ) / frequency - 1;
*PWMxMR0 = divisor;
*PWMxMRc = ( divisor * duty ) / 100;
*PWMxLER = 1 | ( 1 << ( chid + 1 ) );
PWM_MATCHCFG_Type PWMMatchCfgDat;
PINSEL_CFG_Type PinCfg;
u32 divisor = platform_pwm_get_clock( id ) / frequency - 1;
PWM_MatchUpdate(PWM1, 0, divisor, PWM_MATCH_UPDATE_NOW); // PWM1 cycle rate
PWM_MatchUpdate(PWM1, id, ( divisor * duty ) / 100, PWM_MATCH_UPDATE_NOW); // PWM1 channel edge position
if ( id > 1 ) // Channel one is permanently single-edge
PWM_ChannelConfig( PWM1, id, PWM_CHANNEL_SINGLE_EDGE );
PWMMatchCfgDat.IntOnMatch = DISABLE;
PWMMatchCfgDat.MatchChannel = id;
PWMMatchCfgDat.ResetOnMatch = DISABLE;
PWMMatchCfgDat.StopOnMatch = DISABLE;
PWM_ConfigMatch(PWM1, &PWMMatchCfgDat);
PWM_ChannelCmd(PWM1, id, ENABLE);
return platform_pwm_get_clock( id ) / divisor;
}
@ -419,20 +397,15 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
u32 platform_pwm_op( unsigned id, int op, u32 data )
{
u32 res = 0;
unsigned pwmid = id / 6;
PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ];
PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ];
switch( op )
{
case PLATFORM_PWM_OP_START:
*PWMxPCR = PWM_ENABLE_1 | PWM_ENABLE_2 | PWM_ENABLE_3 | PWM_ENABLE_4 | PWM_ENABLE_5 | PWM_ENABLE_6;
*PWMxTCR = PWM_ENABLE | PWM_MODE;
PWM_Cmd(PWM1, ENABLE);
break;
case PLATFORM_PWM_OP_STOP:
*PWMxPCR = 0;
*PWMxTCR = PWM_RESET;
PWM_Cmd(PWM1, DISABLE);
break;
case PLATFORM_PWM_OP_SET_CLOCK:
@ -447,8 +420,6 @@ u32 platform_pwm_op( unsigned id, int op, u32 data )
return res;
}
*/
// ****************************************************************************
// Platform specific modules go here

View File

@ -40,6 +40,7 @@
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\
_ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map )
@ -54,7 +55,7 @@
#define NUM_PIO 5
#define NUM_SPI 0
#define NUM_UART 4
#define NUM_PWM 0
#define NUM_PWM 6
#define NUM_ADC 0
#define NUM_CAN 0
// If virtual timers are enabled, the last timer will be used only for them