Skip to content

Commit c16a115

Browse files
U-owner-PC\ownerU-owner-PC\owner
authored andcommitted
Merge remote-tracking branch 'upstream/master'
2 parents 51efd61 + 1b2a621 commit c16a115

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+70126
-86
lines changed

libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC81X/LPC8xx.h

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -368,23 +368,46 @@ typedef struct { /*!< (@ 0x40028000) WKT Structure
368368
} LPC_WKT_TypeDef;
369369
/*@}*/ /* end of group LPC8xx_WKT */
370370

371-
372371
/*------------- Multi-Rate Timer(MRT) --------------------------------------------------*/
373-
typedef struct {
374-
__IO uint32_t INTVAL;
375-
__IO uint32_t TIMER;
376-
__IO uint32_t CTRL;
377-
__IO uint32_t STAT;
378-
} MRT_Channel_cfg_Type;
379-
380-
typedef struct {
381-
MRT_Channel_cfg_Type Channel[4];
382-
uint32_t Reserved0[1];
383-
__IO uint32_t IDLE_CH;
384-
__IO uint32_t IRQ_FLAG;
372+
//New, Copied from lpc824
373+
/**
374+
* @brief Multi-Rate Timer (MRT) (MRT)
375+
*/
376+
typedef struct { /*!< (@ 0x40004000) MRT Structure */
377+
__IO uint32_t INTVAL0; /*!< (@ 0x40004000) MRT0 Time interval value register. This value
378+
is loaded into the TIMER0 register. */
379+
__I uint32_t TIMER0; /*!< (@ 0x40004004) MRT0 Timer register. This register reads the
380+
value of the down-counter. */
381+
__IO uint32_t CTRL0; /*!< (@ 0x40004008) MRT0 Control register. This register controls
382+
the MRT0 modes. */
383+
__IO uint32_t STAT0; /*!< (@ 0x4000400C) MRT0 Status register. */
384+
__IO uint32_t INTVAL1; /*!< (@ 0x40004010) MRT0 Time interval value register. This value
385+
is loaded into the TIMER0 register. */
386+
__I uint32_t TIMER1; /*!< (@ 0x40004014) MRT0 Timer register. This register reads the
387+
value of the down-counter. */
388+
__IO uint32_t CTRL1; /*!< (@ 0x40004018) MRT0 Control register. This register controls
389+
the MRT0 modes. */
390+
__IO uint32_t STAT1; /*!< (@ 0x4000401C) MRT0 Status register. */
391+
__IO uint32_t INTVAL2; /*!< (@ 0x40004020) MRT0 Time interval value register. This value
392+
is loaded into the TIMER0 register. */
393+
__I uint32_t TIMER2; /*!< (@ 0x40004024) MRT0 Timer register. This register reads the
394+
value of the down-counter. */
395+
__IO uint32_t CTRL2; /*!< (@ 0x40004028) MRT0 Control register. This register controls
396+
the MRT0 modes. */
397+
__IO uint32_t STAT2; /*!< (@ 0x4000402C) MRT0 Status register. */
398+
__IO uint32_t INTVAL3; /*!< (@ 0x40004030) MRT0 Time interval value register. This value
399+
is loaded into the TIMER0 register. */
400+
__I uint32_t TIMER3; /*!< (@ 0x40004034) MRT0 Timer register. This register reads the
401+
value of the down-counter. */
402+
__IO uint32_t CTRL3; /*!< (@ 0x40004038) MRT0 Control register. This register controls
403+
the MRT0 modes. */
404+
__IO uint32_t STAT3; /*!< (@ 0x4000403C) MRT0 Status register. */
405+
__I uint32_t RESERVED0[45];
406+
__I uint32_t IDLE_CH; /*!< (@ 0x400040F4) Idle channel register. This register returns
407+
the number of the first idle channel. */
408+
__IO uint32_t IRQ_FLAG; /*!< (@ 0x400040F8) Global interrupt flag register */
385409
} LPC_MRT_TypeDef;
386410

387-
388411
/*------------- Universal Asynchronous Receiver Transmitter (USART) -----------*/
389412
/** @addtogroup LPC8xx_UART LPC8xx Universal Asynchronous Receiver/Transmitter
390413
@{

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X/device.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#define DEVICE_SERIAL_FC 1
3030

3131
#define DEVICE_I2C 1
32-
#define DEVICE_I2CSLAVE 0
32+
#define DEVICE_I2CSLAVE 1
3333

3434
#define DEVICE_SPI 1
3535
#define DEVICE_SPISLAVE 1
@@ -40,7 +40,7 @@
4040

4141
#define DEVICE_ETHERNET 0
4242

43-
#define DEVICE_PWMOUT 0
43+
#define DEVICE_PWMOUT 1
4444

4545
#define DEVICE_SEMIHOST 0
4646
#define DEVICE_LOCALFILESYSTEM 0

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC81X/objects.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ struct spi_s {
4343
unsigned char spi_n;
4444
};
4545

46+
struct pwmout_s {
47+
LPC_SCT_TypeDef* pwm;
48+
uint32_t pwm_ch;
49+
};
50+
4651
#include "gpio_object.h"
4752

4853
#ifdef __cplusplus
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "mbed_assert.h"
17+
#include "pwmout_api.h"
18+
#include "cmsis.h"
19+
#include "pinmap.h"
20+
#include "mbed_error.h"
21+
22+
// Ported from LPC824 and adapted.
23+
24+
#if DEVICE_PWMOUT
25+
26+
#define PWM_IRQn SCT_IRQn
27+
28+
// Bit flags for used SCT Outputs
29+
static unsigned char sct_used = 0;
30+
static int sct_inited = 0;
31+
32+
// Find available output channel
33+
// Max number of PWM outputs is 4 on LPC812
34+
static int get_available_sct() {
35+
int i;
36+
37+
// Find available output channel 0..3
38+
// Also need one Match register per channel
39+
for (i = 0; i < CONFIG_SCT_nOU; i++) {
40+
// for (i = 0; i < 4; i++) {
41+
if ((sct_used & (1 << i)) == 0)
42+
return i;
43+
}
44+
return -1;
45+
}
46+
47+
// Any Port pin may be used for PWM.
48+
// Max number of PWM outputs is 4
49+
void pwmout_init(pwmout_t* obj, PinName pin) {
50+
MBED_ASSERT(pin != (uint32_t)NC);
51+
52+
int sct_n = get_available_sct();
53+
if (sct_n == -1) {
54+
error("No available SCT Output");
55+
}
56+
57+
sct_used |= (1 << sct_n);
58+
59+
obj->pwm = (LPC_SCT_TypeDef*)LPC_SCT;
60+
obj->pwm_ch = sct_n;
61+
62+
LPC_SCT_TypeDef* pwm = obj->pwm;
63+
64+
// Init SCT on first use
65+
if (! sct_inited) {
66+
sct_inited = 1;
67+
68+
// Enable the SCT clock
69+
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);
70+
71+
// Clear peripheral reset the SCT:
72+
LPC_SYSCON->PRESETCTRL |= (1 << 8);
73+
74+
// Two 16-bit counters, autolimit (ie reset on Match_0)
75+
pwm->CONFIG &= ~(0x1);
76+
pwm->CONFIG |= (1 << 17);
77+
78+
// halt and clear the counter
79+
pwm->CTRL_L |= (1 << 2) | (1 << 3);
80+
81+
// System Clock (30 Mhz) -> Prescaler -> us_ticker (1 MHz)
82+
pwm->CTRL_L &= ~(0x7F << 5);
83+
pwm->CTRL_L |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5);
84+
85+
pwm->EVENT[0].CTRL = (1 << 12) | 0; // Event_0 on Match_0
86+
pwm->EVENT[0].STATE = 0xFFFFFFFF; // All states
87+
88+
// unhalt the counter:
89+
// - clearing bit 2 of the CTRL register
90+
pwm->CTRL_L &= ~(1 << 2);
91+
92+
// Not using IRQs
93+
//NVIC_SetVector(PWM_IRQn, (uint32_t)pwm_irq_handler);
94+
//NVIC_EnableIRQ(PWM_IRQn);
95+
}
96+
97+
// LPC81x has only one SCT and 4 Outputs
98+
// LPC82x has only one SCT and 6 Outputs
99+
// LPC1549 has 4 SCTs and 16 Outputs
100+
switch(sct_n) {
101+
case 0:
102+
// SCTx_OUT0
103+
LPC_SWM->PINASSIGN[6] &= ~0xFF000000;
104+
LPC_SWM->PINASSIGN[6] |= (pin << 24);
105+
break;
106+
case 1:
107+
// SCTx_OUT1
108+
LPC_SWM->PINASSIGN[7] &= ~0x000000FF;
109+
LPC_SWM->PINASSIGN[7] |= (pin);
110+
break;
111+
case 2:
112+
// SCTx_OUT2
113+
LPC_SWM->PINASSIGN[7] &= ~0x0000FF00;
114+
LPC_SWM->PINASSIGN[7] |= (pin << 8);
115+
break;
116+
case 3:
117+
// SCTx_OUT3
118+
LPC_SWM->PINASSIGN[7] &= ~0x00FF0000;
119+
LPC_SWM->PINASSIGN[7] |= (pin << 16);
120+
break;
121+
default:
122+
break;
123+
}
124+
125+
pwm->EVENT[sct_n + 1].CTRL = (1 << 12) | (sct_n + 1); // Event_n on Match_n
126+
pwm->EVENT[sct_n + 1].STATE = 0xFFFFFFFF; // All states
127+
128+
pwm->OUT[sct_n].SET = (1 << 0); // All PWM channels are SET on Event_0
129+
pwm->OUT[sct_n].CLR = (1 << (sct_n + 1)); // PWM ch is CLRed on Event_(ch+1)
130+
131+
// default to 20ms: standard for servos, and fine for e.g. brightness control
132+
pwmout_period_ms(obj, 20); // 20ms period
133+
pwmout_write (obj, 0.0); // 0ms pulsewidth, dutycycle 0
134+
}
135+
136+
void pwmout_free(pwmout_t* obj) {
137+
// PWM channel is now free
138+
sct_used &= ~(1 << obj->pwm_ch);
139+
140+
// Disable the SCT clock when all channels free
141+
if (sct_used == 0) {
142+
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 8);
143+
sct_inited = 0;
144+
};
145+
}
146+
147+
// Set new dutycycle (0.0 .. 1.0)
148+
void pwmout_write(pwmout_t* obj, float value) {
149+
//value is new dutycycle
150+
if (value < 0.0f) {
151+
value = 0.0;
152+
} else if (value > 1.0f) {
153+
value = 1.0;
154+
}
155+
156+
// Match_0 is PWM period. Compute new endtime of pulse for current channel
157+
uint32_t t_off = (uint32_t)((float)(obj->pwm->MATCHREL[0].L) * value);
158+
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = t_off; // New endtime
159+
}
160+
161+
// Get dutycycle (0.0 .. 1.0)
162+
float pwmout_read(pwmout_t* obj) {
163+
uint32_t t_period = obj->pwm->MATCHREL[0].L;
164+
165+
//Sanity check
166+
if (t_period == 0) {
167+
return 0.0;
168+
};
169+
170+
uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L;
171+
float v = (float)t_off/(float)t_period;
172+
//Sanity check
173+
return (v > 1.0f) ? (1.0f) : (v);
174+
}
175+
176+
// Set the PWM period, keeping the duty cycle the same (for this channel only!).
177+
void pwmout_period(pwmout_t* obj, float seconds){
178+
pwmout_period_us(obj, seconds * 1000000.0f);
179+
}
180+
181+
// Set the PWM period, keeping the duty cycle the same (for this channel only!).
182+
void pwmout_period_ms(pwmout_t* obj, int ms) {
183+
pwmout_period_us(obj, ms * 1000);
184+
}
185+
186+
// Set the PWM period, keeping the duty cycle the same (for this channel only!).
187+
void pwmout_period_us(pwmout_t* obj, int us) {
188+
189+
uint32_t t_period = obj->pwm->MATCHREL[0].L; // Current PWM period
190+
obj->pwm->MATCHREL[0].L = (uint64_t)us; // New PWM period
191+
192+
//Keep the dutycycle for the new PWM period
193+
//Should really do this for all active channels!!
194+
//This problem exists in all mbed libs.
195+
196+
//Sanity check
197+
if (t_period == 0) {
198+
return;
199+
// obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = 0; // New endtime for this channel
200+
}
201+
else {
202+
uint32_t t_off = obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L;
203+
float v = (float)t_off/(float)t_period;
204+
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = (uint64_t)((float)us * (float)v); // New endtime for this channel
205+
}
206+
}
207+
208+
209+
//Set pulsewidth
210+
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
211+
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
212+
}
213+
214+
//Set pulsewidth
215+
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms){
216+
pwmout_pulsewidth_us(obj, ms * 1000);
217+
}
218+
219+
//Set pulsewidth
220+
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
221+
222+
//Should add Sanity check to make sure pulsewidth < period!
223+
obj->pwm->MATCHREL[(obj->pwm_ch) + 1].L = (uint64_t)us; // New endtime for this channel
224+
}
225+
226+
#endif

0 commit comments

Comments
 (0)