OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [cortexm/] [lpc17xx/] [var/] [current/] [src/] [lpc17xx_misc.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      lpc17xx_misc.c
4
//
5
//      Cortex-M LPC17XX HAL functions
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2010 Free Software Foundation, Inc.                        
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    nickg, ilijak
43
// Date:         2010-12-12
44
// Description:  
45
//
46
//####DESCRIPTIONEND####
47
//
48
//========================================================================
49
 
50
 
51
#include <pkgconf/hal.h>
52
#include <pkgconf/hal_cortexm.h>
53
#include <pkgconf/hal_cortexm_lpc17xx.h>
54
#ifdef CYGPKG_KERNEL
55
# include <pkgconf/kernel.h>
56
#endif
57
 
58
#include <cyg/infra/diag.h>
59
#include <cyg/infra/cyg_type.h>
60
#include <cyg/infra/cyg_trac.h>        // tracing macros
61
#include <cyg/infra/cyg_ass.h>         // assertion macros
62
 
63
#include <cyg/hal/hal_arch.h>          // HAL header
64
#include <cyg/hal/hal_intr.h>          // HAL header
65
#include <cyg/hal/hal_if.h>            // HAL header
66
 
67
#include <cyg/hal/lpc17xx_misc.h>
68
 
69
 
70
//===========================================================================
71
//                               DEFINES
72
//===========================================================================
73
 
74
cyg_uint32      hal_lpc17xx_sysclk;
75
cyg_uint32      hal_cortexm_systick_clock;
76
 
77
cyg_uint32      hal_get_lpc_cpu_clock(void);
78
 
79
void            hal_start_clocks(void);
80
 
81
void            hal_lpc_start_main_clock(void);
82
void            hal_lpc_start_usb_clock(void);
83
#if defined(CYGHWR_HAL_CORTEXM_LPC17XX_CLKOUT)
84
void            hal_lpc_clock_out(void);
85
#endif
86
//==========================================================================
87
 
88
#ifdef CYG_HAL_STARTUP_ROM
89
 
90
//===========================================================================
91
// LPC17xx Code Read Protection field field
92
//===========================================================================
93
 
94
// Note: LPC17xx Code Read Protection field field must be present in
95
//       LPC17xx flash image and ocupy a word at 0x000002FC
96
 
97
// For ".lpc17xx_crp" section definition see MLT files.
98
 
99
const cyg_uint32 LPC17XX_CRP __attribute__((section(".lpc17xxcrp"), used)) = 0xFFFFFFFF;
100
 
101
#endif // CYG_HAL_STARTUP_ROM
102
 
103
const cyg_uint32* hal_lpc17xx_crp_p(void)
104
{
105
    return &LPC17XX_CRP;
106
}
107
 
108
void
109
hal_variant_init(void)
110
{
111
#if 1                                  /* !defined(CYG_HAL_STARTUP_RAM) */
112
    hal_start_clocks();
113
#endif
114
 
115
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
116
    hal_if_init();
117
#endif
118
}
119
 
120
//==========================================================================
121
// Setup up system clocks
122
//
123
// Set up clocks from configuration. In the future this should be extended so
124
// that clock rates can be changed at runtime.
125
 
126
 
127
void CYGOPT_HAL_LPC17XX_MISC_FLASH_SECTION_ATTR
128
hal_start_clocks(void)
129
{
130
    // Main clock - for everything except USB
131
    hal_lpc_start_main_clock();
132
 
133
    // USB clock
134
    hal_lpc_start_usb_clock();
135
 
136
#if defined CYGHWR_HAL_CORTEXM_LPC17XX_CLKOUT
137
    hal_lpc_clock_out();
138
#endif
139
}
140
 
141
 
142
void CYGOPT_HAL_LPC17XX_MISC_FLASH_SECTION_ATTR
143
hal_lpc_start_main_clock(void)
144
{
145
    CYG_ADDRESS     scb_base_p;
146
    cyg_uint32      regval;
147
 
148
    scb_base_p = CYGHWR_HAL_LPC17XX_REG_SCB_BASE;
149
 
150
    HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0STAT, regval);
151
    if (regval & CYGHWR_HAL_LPC17XX_REG_PLL0STAT_PLLC) {
152
 
153
        // Enable PLL, disconnected
154
        HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0CON,
155
                         CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLE);
156
        HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0xaa);
157
        HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0x55);
158
    }
159
    // Disable PLL, disconnected
160
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0CON, 0x00);
161
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0xaa);
162
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0x55);
163
 
164
    // Enables main oscillator and wait until it is usable
165
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_SCS,
166
                     CYGHWR_HAL_LPC17XX_REG_SCS_OSCEN);
167
    do {
168
        HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_SCS, regval);
169
    } while (!(regval & CYGHWR_HAL_LPC17XX_REG_SCS_OSCSTAT));
170
 
171
 
172
    // Select main OSC, 12MHz, as the PLL clock source
173
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_CLKSRCSEL,
174
                     CYGHWR_HAL_LPC17XX_REG_CLKSRCSEL_MAIN);
175
 
176
    // Configure PLL multiplier and pre divider according to configuration
177
    // values
178
    regval = ((CYGHWR_HAL_CORTEXM_LPC17XX_PLL0_MUL - 1) |
179
              (CYGHWR_HAL_CORTEXM_LPC17XX_PLL0_DIV - 1) << 16);
180
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0CFG, regval);
181
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0xaa);
182
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0x55);
183
 
184
    // Enable PLL, disconnected
185
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0CON,
186
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLE);
187
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0xaa);
188
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0x55);
189
 
190
    // Set CPU clock divider
191
    regval = CYGHWR_HAL_CORTEXM_LPC17XX_CPU_CLK_DIV - 1;
192
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_CCLKCFG, regval);
193
 
194
    // Check lock bit status
195
    do {
196
        HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0STAT, regval);
197
    } while (!(regval & CYGHWR_HAL_LPC17XX_REG_PLL0STAT_PLOCK));
198
 
199
    // Connect CPU clock
200
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0CON,
201
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLE |
202
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLC);
203
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0xaa);
204
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0FEED, 0x55);
205
 
206
    // Check connect bit status
207
    do {
208
        HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL0STAT, regval);
209
    } while (!(regval & CYGHWR_HAL_LPC17XX_REG_PLL0STAT_PLLC));
210
 
211
    // Calculate system clock from configuration
212
    hal_lpc17xx_sysclk = CYGHWR_HAL_CORTEXM_LPC17XX_CLOCK_SPEED;
213
    hal_cortexm_systick_clock = hal_lpc17xx_sysclk;
214
}
215
 
216
void CYGOPT_HAL_LPC17XX_MISC_FLASH_SECTION_ATTR
217
hal_lpc_start_usb_clock(void)
218
{
219
    CYG_ADDRESS     scb_base_p;
220
    cyg_uint32      regval;
221
 
222
    scb_base_p = CYGHWR_HAL_LPC17XX_REG_SCB_BASE;
223
 
224
    // Configure PLL multiplier and pre divider according to
225
    // configuration values
226
    regval = ((CYGHWR_HAL_CORTEXM_LPC17XX_PLL1_MUL - 1) |
227
              (CYGHWR_HAL_CORTEXM_LPC17XX_PLL1_DIV - 1) << 5);
228
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1CFG, regval);
229
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0xaa);
230
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0x55);
231
 
232
    // Enable PLL, disconnected
233
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1CON,
234
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLE);
235
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0xaa);
236
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0x55);
237
 
238
    do {
239
        HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1STAT, regval);
240
    } while (!(regval & CYGHWR_HAL_LPC17XX_REG_PLL1STAT_PLOCK));
241
 
242
    // Connect USB clock
243
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1CON,
244
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLE |
245
                     CYGHWR_HAL_LPC17XX_REG_PLLCON_PLLC);
246
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0xaa);
247
    HAL_WRITE_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1FEED, 0x55);
248
 
249
    // Check connect bit status
250
    do {
251
        HAL_READ_UINT32(scb_base_p + CYGHWR_HAL_LPC17XX_REG_PLL1STAT, regval);
252
    } while (!(regval & CYGHWR_HAL_LPC17XX_REG_PLL1STAT_PLLC));
253
}
254
 
255
#ifdef CYGHWR_HAL_CORTEXM_LPC17XX_CLKOUT
256
void CYGOPT_HAL_LPC17XX_MISC_FLASH_SECTION_ATTR
257
hal_lpc_clock_out(void)
258
{
259
    cyg_uint32      regval;
260
 
261
    CYGHWR_HAL_LPC17XX_PIN_GET(CYGHWR_HAL_LPC17XX_REG_PINSEL3, regval);
262
    regval &= ~0x00c00000;
263
    regval |= 0x00400000;
264
    CYGHWR_HAL_LPC17XX_PIN_SET(CYGHWR_HAL_LPC17XX_REG_PINSEL3, regval);
265
 
266
    HAL_WRITE_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE +
267
                     CYGHWR_HAL_LPC17XX_REG_CLKOUTCFG,
268
                     CYGHWR_HAL_CORTEXM_LPC17XX_CLKOUT_SET);
269
}
270
#endif // CYGHWR_HAL_CORTEXM_LPC17XX_CLKOUT
271
 
272
 
273
cyg_uint32
274
hal_lpc_get_cpu_clock(void)
275
{
276
    cyg_uint32      regval,
277
                    pll0stat_div,
278
                    pll0stat_mul,
279
                    cclkcfg;
280
 
281
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE +
282
                    CYGHWR_HAL_LPC17XX_REG_PLL0STAT, pll0stat_div);
283
    pll0stat_mul = ((pll0stat_div >> 16) & 0xff) + 1;
284
    pll0stat_div = 2 * ((pll0stat_div & 0x7fff) + 1);
285
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE +
286
                    CYGHWR_HAL_LPC17XX_REG_CCLKCFG, cclkcfg);
287
    cclkcfg = (cclkcfg & 0xff) + 1;
288
 
289
    regval =
290
        CYGHWR_HAL_CORTEXM_LPC17XX_XTAL_FREQ * pll0stat_div / pll0stat_mul /
291
        cclkcfg;
292
 
293
    return regval;
294
}
295
 
296
 
297
//===========================================================================
298
// Get peripheral clock for a certain peripheral
299
//===========================================================================
300
cyg_uint32
301
hal_lpc_get_pclk(cyg_uint32 pclk_id)
302
{
303
    static const cyg_uint8 divider_tbl[4] = {
304
        4, 1, 2, 8
305
    };
306
    cyg_uint32      pclkselreg;
307
    cyg_uint32      regval;
308
    cyg_uint8       divider;
309
 
310
    CYG_ASSERT(pclk_id >= CYNUM_HAL_LPC17XX_PCLK_WDT &&
311
               pclk_id <= CYNUM_HAL_LPC17XX_PCLK_SYSCON,
312
               "Invalid peripheral clock ID");
313
 
314
    // Decide if we need PCLKSEL0 or PCLKSEL1
315
    pclkselreg = ((pclk_id <= CYNUM_HAL_LPC17XX_PCLK_ACF) ?
316
                  CYGHWR_HAL_LPC17XX_REG_PCLKSEL0 :
317
                  CYGHWR_HAL_LPC17XX_REG_PCLKSEL1);
318
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE + pclkselreg, regval);
319
    regval = (regval >> ((pclk_id & 0xF) << 1)) & 0x03;
320
    divider = divider_tbl[regval];
321
    if ((8 == divider) && (pclk_id >= CYNUM_HAL_LPC17XX_PCLK_CAN1)
322
        && (pclk_id <= CYNUM_HAL_LPC17XX_PCLK_ACF)) {
323
        divider = 6;
324
    }
325
    return CYGHWR_HAL_CORTEXM_LPC17XX_CLOCK_SPEED / divider;
326
}
327
 
328
 
329
//===========================================================================
330
// Set peripheral clock
331
//===========================================================================
332
void
333
hal_lpc_set_pclk(cyg_uint32 peripheral_id, cyg_uint8 divider)
334
{
335
    static const cyg_uint8 clock_tbl[5] = {
336
        0x01,                          // divider 1
337
        0x02,                          // divider 2
338
        0x00,                          // divider 4
339
        0x03,                          // divider 6
340
        0x03                           // divider 8
341
    };
342
    cyg_uint32      clock;
343
    cyg_uint32      pclkselreg;
344
    cyg_uint32      regval;
345
 
346
    CYG_ASSERT(peripheral_id >= CYNUM_HAL_LPC17XX_PCLK_WDT &&
347
               peripheral_id <= CYNUM_HAL_LPC17XX_PCLK_SYSCON,
348
               "Invalid peripheral clock ID");
349
    CYG_ASSERT(divider <= 8, "Wrong peripheral clock divider value");
350
 
351
    // Decide if we need PCLKSEL0 or PCLKSEL1
352
    pclkselreg = (peripheral_id <= CYNUM_HAL_LPC17XX_PCLK_ACF) ?
353
        CYGHWR_HAL_LPC17XX_REG_PCLKSEL0 : CYGHWR_HAL_LPC17XX_REG_PCLKSEL1;
354
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE + pclkselreg, regval);
355
    clock = clock_tbl[divider >> 1];
356
    regval &= ~(0x03 << ((peripheral_id & 0xF) << 1));
357
    regval |= (clock << ((peripheral_id & 0xF) << 1));
358
    HAL_WRITE_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE + pclkselreg, regval);
359
}
360
 
361
 
362
//===========================================================================
363
// Set pin function
364
//===========================================================================
365
void
366
hal_lpc_set_pin_function(cyg_uint8 port, cyg_uint8 pin, cyg_uint8 function)
367
{
368
    cyg_uint32      regval;
369
    cyg_uint8       pinsel_reg = port << 1;
370
 
371
    CYG_ASSERT(port <= 4, "Port value out of bounds");
372
    CYG_ASSERT(pin <= 31, "Pin value out of bounds");
373
    CYG_ASSERT(function <= 3, "Invalid function value");
374
 
375
    pinsel_reg += (pin > 15) ? 1 : 0;
376
    pinsel_reg <<= 2;
377
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_PIN_BASE + pinsel_reg, regval);
378
    regval &= ~(0x03 << ((pin & 0xF) << 1));
379
    regval |= (function << ((pin & 0xF) << 1));
380
    HAL_WRITE_UINT32(CYGHWR_HAL_LPC17XX_REG_PIN_BASE + pinsel_reg, regval);
381
}
382
 
383
//===========================================================================
384
// Enable/Disable power for certain peripheral
385
//===========================================================================
386
void
387
hal_lpc_set_power(cyg_uint8 pconp_id, int on)
388
{
389
    cyg_uint32      regval;
390
 
391
    CYG_ASSERT(pconp_id >= CYNUM_HAL_LPC17XX_PCONP_TIMER0 &&
392
               pconp_id <= CYNUM_HAL_LPC17XX_PCONP_USB,
393
               "Invalid peripheral power ID");
394
    HAL_READ_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE +
395
                    CYGHWR_HAL_LPC17XX_REG_PCONP, regval);
396
    if (on) {
397
        regval |= (0x01 << pconp_id);
398
    } else {
399
        regval &= ~(0x01 << pconp_id);
400
    }
401
 
402
    HAL_WRITE_UINT32(CYGHWR_HAL_LPC17XX_REG_SCB_BASE +
403
                     CYGHWR_HAL_LPC17XX_REG_PCONP, regval);
404
}
405
 
406
 
407
//==========================================================================
408
// UART baud rate
409
//
410
// Set the baud rate divider of a UART based on the requested rate and
411
// the current APB clock settings.
412
 
413
void
414
hal_plf_uart_setbaud(cyg_uint32 base, cyg_uint32 baud)
415
{
416
    cyg_uint32      periph_id = CYNUM_HAL_LPC17XX_PCLK_UART0;
417
    cyg_uint16      divider;
418
 
419
    if (CYGHWR_HAL_LPC17XX_REG_UART1_BASE == base)
420
        periph_id = CYNUM_HAL_LPC17XX_PCLK_UART1;
421
    divider = CYG_HAL_CORTEXM_LPC17XX_BAUD_GENERATOR(periph_id, baud);
422
    // Set baudrate
423
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LPC17XX_REG_UxLCR,
424
                     CYGHWR_HAL_LPC17XX_REG_UxLCR_DLAB);
425
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LPC17XX_REG_UxDLM, divider >> 8);
426
    HAL_WRITE_UINT32(base + CYGHWR_HAL_LPC17XX_REG_UxDLL, divider & 0xFF);
427
}
428
 
429
//==========================================================================
430
// EOF lpc17xx_misc.c

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.