This is sample program for Nucleo L152RE (and F401RE & F411RE) mbed-rtos. You need to modify mbed-src and mbed-rtos before compile it.

Dependencies:   mbed-rtos mbed-src SetRTC

Fork of GR-PEACH_test_on_rtos_works_well by Kenji Arai

Please refer below link.
/users/kenjiArai/notebook/necleo-l152re-rtos-sample-also-for-f401re--f411re-/

debug_tools_L152_F4x1RE/mon_hw_STM32.cpp

Committer:
kenjiArai
Date:
2015-05-20
Revision:
13:d0d1da1fae4c
Parent:
10:1c0f58b9c048

File content as of revision 13:d0d1da1fae4c:

/*
 * mbed Application program for the ST NUCLEO Board
 * Monitor program Ver.3 for only for STM32F401RE,F411RE & STM32L152RE
 *
 *  Copyright (c) 2010-2015 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Started:  May        9th, 2010
 *      Created:  May       15th, 2010
 *          release as "monitor_01" http://mbed.org/users/kenjiArai/code/monitor_01/
 *      Spareted: June      25th, 2014      mon() & mon_hw()
 *      restart:  July      12th, 2014
 *      Revised:  April     25th, 2015      Bug fix ('o' command) pointed out by Topi Makinen
 *      Revised:  April     26th, 2015      Change Port output speed (set High speed)
 *      Revised:  May       16th, 2015
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_L152RE)

//  Include ---------------------------------------------------------------------------------------
#include "mbed.h"
#include "debug_common.h"
#include "mon_hw_config.h"
#include "mon_hw_common.h"
#include "mon_hw_STM32.h"

//  Object ----------------------------------------------------------------------------------------

//  Definition ------------------------------------------------------------------------------------
// USB Frequency
#define USB_FREQ_H          48100000
#define USB_FREQ_L          47900000

//  RAM -------------------------------------------------------------------------------------------
uint32_t SystemFrequency;
uint8_t quitflag;

uint32_t reg_save0, reg_save1, reg_save2, reg_save3, reg_save4, reg_save5, reg_save6;

//  ROM / Constant data ---------------------------------------------------------------------------
#if defined(TARGET_NUCLEO_F401RE)
char *const xmon_msg =
    "HW monitor only for mbed Nucleo F401RE created on UTC:"__DATE__"("__TIME__")";

#if USE_MEM
const uint32_t mem_range[][2] = {   // Memory access range
    { 0x08000000, 0x0807ffff },     // On-chip Flash memory, 512KB Flash
    { 0x1fff0000, 0x1fff7a0f },     // System memory
    { 0x1fffc000, 0x1fffc007 },     // Option bytes
    { 0x20000000, 0x20017fff },     // Main Embedded SRAM, 96KB SRAM
    { 0x40000000, 0x5003ffff }      // IO area
};
#endif // USE_MEM
#elif defined(TARGET_NUCLEO_F411RE)
char *const xmon_msg =
    "HW monitor only for mbed Nucleo F411RE created on UTC:"__DATE__"("__TIME__")";

#if USE_MEM
const uint32_t mem_range[][2] = {   // Memory access range
    { 0x08000000, 0x0807ffff },     // On-chip Flash memory, 512KB Flash
    { 0x1fff0000, 0x1fff7a0f },     // System memory
    { 0x1fffc000, 0x1fffc007 },     // Option bytes
    { 0x20000000, 0x2001ffff },     // Main Embedded SRAM, 128KB SRAM
    { 0x40000000, 0x5003ffff }      // IO area
};
#endif // USE_MEM
#elif defined(TARGET_NUCLEO_L152RE)
char *const xmon_msg =
    "HW monitor only for mbed Nucleo L152RE created on UTC:"__DATE__"("__TIME__")";

#if USE_MEM
const uint32_t mem_range[][2] = {   // Memory access range
    { 0x08000000, 0x0807ffff },     // On-chip Flash memory, 512KB Flash
    { 0x08080000, 0x08083fff },     // EEPROM, 16KB
    { 0x1ff00000, 0x1ff01fff },     // System memory
    { 0x1ff80000, 0x1ff8009f },     // Option bytes
    { 0x20000000, 0x20013fff },     // Main Embedded SRAM, 32KB SRAM
    { 0x40000000, 0x400267ff }      // IO area
};
#endif // USE_MEM
#endif

char *const hmsg0 = "m  - Entry Memory Mode";
char *const hmsg1 = "m>? -> Aditinal functions can see by ?";
char *const hmsg2 = "r  - Entry Register Mode";
char *const hmsg3 = "r>? -> Aditinal functions can see by ?";
char *const hmsg4 = "s  - System Clock -> sf, System / CPU information -> sc";
char *const hmsg5 = "q  - Quit (back to called routine)";
char *const hmsg6 = "p  - Entry Port Mode";
char *const hmsg7 = "p>? -> Aditinal functions can see by ?";

char *const mrmsg0 = "Enter Register Mode u,i,s,t,a,d,l,w,c & ? for help";
#if (USE_UART==1) || (USE_SPI==1) || (USE_I2C == 1)
char *const mrmsg1 = "------";
char *const mrmsg2 = "USART";
//
char *const mrmsg4 = "I2C";
//
char *const mrmsg6 = "SPI";
//
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
char *const mrmsg3 = "Enter u1,u2,u6 and u* for all";
char *const mrmsg5 = "Enter i1,i2,i3 and i* for all";
char *const mrmsg7 = "Enter s1,s2,s3,s4 and s* for all";
#elif defined(TARGET_NUCLEO_L152RE)
char *const mrmsg3 = "Enter u1,u2,u3,u5 and u* for all";
char *const mrmsg5 = "Enter i1,i2 and i* for all";
char *const mrmsg7 = "Enter s1,s2,s3 and s* for all";
#endif
#endif  // (USE_UART==1) || (USE_SPI==1) || (USE_I2C == 1)
char *const mrmsg8 = "Return to All Mode";

//-------------------------------------------------------------------------------------------------
//  Control Program
//-------------------------------------------------------------------------------------------------
// No function
static void not_yet_impliment( void )
{
    PRINTF("Not implimented yet");
    put_rn();
}

// No function
#if (USE_MEM==0)||(USE_PORT==0)||(USE_UART==0)||(USE_SPI==0)||(USE_I2C==0)||(USE_SYS==0)
static void not_select( void )
{
    PRINTF("Not select the function (refer mon_hw_config.h)");
    put_rn();
}
#endif

//  Help Massage
void hw_msg_hlp ( void )
{
    PRINTF(mon_msg);
    put_rn();
    PRINTF(hmsg0);
    put_rn();
    PRINTF(hmsg1);
    put_rn();
    PRINTF(hmsg6);
    put_rn();
    PRINTF(hmsg7);
    put_rn();
    PRINTF(hmsg2);
    put_rn();
    PRINTF(hmsg3);
    put_rn();
    PRINTF(hmsg4);
    put_rn();
    PRINTF(hmsg5);
    put_rn();
}

#if USE_MEM
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
char *const rmsg0 = "FLASH    ";
char *const rmsg1 = "SYS-Mem  ";
char *const rmsg2 = "OPTION   ";
char *const rmsg3 = "SRAM     ";
char *const rmsg4 = "IO       ";
#elif defined(TARGET_NUCLEO_L152RE)
char *const rmsg0 = "FLASH    ";
char *const rmsg1 = "EEPROM   ";
char *const rmsg2 = "SYS-Mem  ";
char *const rmsg3 = "OPTION   ";
char *const rmsg4 = "SRAM     ";
char *const rmsg5 = "IO       ";
#endif

#include "mon_hw_mem.h"
#endif   // USE_MEM


//  Show 16bit register contents
void reg_print(uint16_t size, uint16_t reg)
{
    uint16_t i, j, k, n;

    i = j = k = n = 0;
    switch (size) {
        case SIZE8:
            PRINTF(rgmsg0);
            put_rn();
            i = 8;
            n = 0x80;
            break;
        case SIZE16:
            PRINTF("%s%s", rgmsg1, rgmsg0);
            put_rn();
            i = 16;
            n = 0x8000;
            break;
        case SIZE32:
            PRINTF("0x%08x", reg);
            return;
        default :
            ;
    }
    PUTC(' ');
    for (; i>0; i--) {
        k = n >> (size-i);
        j = reg & k;
        if (j) {
            PUTC('1');
        } else {
            PUTC('0');
        }
        PUTC(' ');
        PUTC(' ');
    }
    PRINTF("  (0x%04x)", reg);
}

#if USE_I2C
void i2c_reg( I2C_TypeDef* I2Cx )
{
    uint16_t reg;

    put_rn();
    reg = I2Cx->CR1;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg0 );
    PRINTF( imsg2 );
    put_rn();
    reg = I2Cx->CR2;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg1 );
    PRINTF( imsg2 );
    put_rn();
    reg = I2Cx->SR1;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg5 );
    PRINTF( imsg3 );
    put_rn();
    reg = I2Cx->SR2;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg6 );
    PRINTF( imsg3 );
    put_rn();
    reg = I2Cx->DR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg2 );
    PRINTF( imsg4 );
    put_rn();
    reg = I2Cx->OAR1;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg7 );
    PRINTF( imsg6 );
    put_rn();
    reg = I2Cx->OAR2;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg8 );
    PRINTF( imsg6 );
    put_rn();
    reg = I2Cx->CCR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg9 );
    PRINTF( imsg7 );
    put_rn();
    reg = I2Cx->TRISE;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg10 );
    PRINTF( imsg8 );
    put_rn();
}
#endif  // USE_I2C

#if USE_SPI
void spi_reg( SPI_TypeDef* SPIx )
{
    uint16_t reg;

    put_rn();
    reg = SPIx->CR1;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg0 );
    PRINTF( imsg2 );
    put_rn();
    reg = SPIx->CR2;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg1 );
    PRINTF( imsg2 );
    put_rn();
    reg = SPIx->SR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg3 );
    PRINTF( imsg3 );
    put_rn();
    reg = SPIx->DR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg2 );
    PRINTF( imsg4 );
    put_rn();
}
#endif  // USE_SPI

#if USE_UART
void usart_reg( USART_TypeDef* USARTx )
{
    uint16_t reg;

    put_rn();
    reg = USARTx->SR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg3 );
    PRINTF( imsg3 );
    put_rn();
    reg = USARTx->DR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg2 );
    PRINTF( imsg4 );
    put_rn();
    reg = USARTx->BRR;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg4 );
    PRINTF( imsg5 );
    put_rn();
    reg = USARTx->CR1;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg0 );
    PRINTF( imsg2 );
    put_rn();
    reg = USARTx->CR2;
    reg_print( SIZE32, reg );
    PRINTF( rnmsg1 );
    PRINTF( imsg2 );
    put_rn();
}
#endif  // USE_UART

#if USE_PORT
void rpt_port_one( GPIO_TypeDef* GPIOx )
{
    uint32_t i;

    PRINTF( " " );
    i = GPIOx->MODER;
    PRINTF( "0x%08x",i );
    i = GPIOx->OTYPER;
    PRINTF( " 0x%04x",i );
    i = GPIOx->OSPEEDR;
    PRINTF( "  0x%08x",i );
    i = GPIOx->PUPDR;
    PRINTF( " 0x%08x",i );
    i = GPIOx->IDR;
    PRINTF( " 0x%04x",i );
    i = GPIOx->ODR;
    PRINTF( " 0x%04x",i );
    put_rn();
}

void rpt_port( void )
{
    PRINTF( pnmsg0 );
    PRINTF( pnmsg1 );
    put_rn();
    PRINTF( pnmsga );
    rpt_port_one( GPIOA );
    PRINTF( pnmsgb );
    rpt_port_one( GPIOB );
    PRINTF( pnmsgc );
    rpt_port_one( GPIOC );
    PRINTF( pnmsgd );
    rpt_port_one( GPIOD );
    PRINTF( pnmsge );
    rpt_port_one( GPIOE );
    PRINTF( pnmsgh );
    rpt_port_one( GPIOH );
}

void port_inf_one( char *ptr )
{
    GPIO_TypeDef* GPIOx;
    uint32_t i,j;
    uint32_t pinpos;

    GPIOx = 0;
    PRINTF( pnmsg2 );
    switch ( *ptr ) {
        case 'a':
            GPIOx = GPIOA;
            PUTC( 'A' );
            break;
        case 'b':
            GPIOx = GPIOB;
            PUTC( 'B' );
            break;
        case 'c':
            GPIOx = GPIOC;
            PUTC( 'C' );
            break;
        case 'd':
            GPIOx = GPIOD;
            PUTC( 'D' );
            break;
        case 'e':
            GPIOx = GPIOE;
            PUTC( 'E' );
            break;
        case 'h':
            GPIOx = GPIOH;
            PUTC( 'H' );
            break;
    }
    i = GPIOx->MODER;
    put_rn();
    PRINTF( "-->Mode Reg.  (0x%08x)",i );
    put_rn();
    for ( pinpos = 0x00; pinpos < 16; pinpos++ ) {
        j = GPIO_MODER_MODER0 & (i >> (pinpos * 2));
        switch (j) {
            case GPIO_Mode_IN:
                PRINTF( "%2d= in", pinpos );
                break;
            case GPIO_Mode_OUT:
                PRINTF( "%2d=out", pinpos );
                break;
            case GPIO_Mode_AF:
                PRINTF( "%2d=alt", pinpos );
                break;
            case GPIO_Mode_AN:
                PRINTF( "%2d=ana", pinpos );
                break;
            default:
                break;
        }
        if ( (pinpos == 3) && (*ptr == 'h') ) {
            break;
        } else {
            if ( pinpos == 7 ) {
                put_rn();
            } else if ( pinpos == 15 ) {
                ;
            } else {
                PRINTF(", ");
            }
        }
    }
    i = GPIOx->OTYPER;
    put_rn();
    PRINTF( "%s type 1=push-pull, 0= open-drain", pnmsg4 );
    put_rn();
    reg_print( SIZE32,i);
    i = GPIOx->OSPEEDR;
    PRINTF( "%s speed [MHz] (0x%08x)", pnmsg4, i );
    put_rn();
    for ( pinpos = 0x00; pinpos < 16; pinpos++ ) {
        j = GPIO_OSPEEDER_OSPEEDR0 & (i >> (pinpos * 2));
        switch (j) {
            case GPIO_Speed_400KHz:
                PRINTF( "%2d=0.4", pinpos );
                break;
            case GPIO_Speed_2MHz:
                PRINTF( "%2d=  2", pinpos );
                break;
            case GPIO_Speed_10MHz:
                PRINTF( "%2d= 10", pinpos );
                break;
            case GPIO_Speed_40MHz:
                PRINTF( "%2d= 40", pinpos );
                break;
            default:
                break;
        }
        if ( (pinpos == 3) && (*ptr == 'h') ) {
            break;
        } else {
            if ( pinpos == 7 ) {
                put_rn();
            } else if ( pinpos == 15) {
                ;
            } else {
                PRINTF(", ");
            }
        }
    }
    i = GPIOx->PUPDR;
    put_rn();
    PRINTF( "-->Pullup(pup)/down(pdn) none(no)(0x%08x)",i );
    put_rn();
    for ( pinpos = 0x00; pinpos < 16; pinpos++ ) {
        j = GPIO_PUPDR_PUPDR0 & (i >> (pinpos * 2));
        switch (j) {
            case GPIO_PuPd_NOPULL:
                PRINTF( "%2d= no", pinpos );
                break;
            case GPIO_PuPd_UP:
                PRINTF( "%2d=pup", pinpos );
                break;
            case GPIO_PuPd_DOWN:
                PRINTF( "%2d=pdn", pinpos );
                break;
            default:
                break;
        }
        if ( (pinpos == 3) && (*ptr == 'h') ) {
            break;
        } else {
            if ( pinpos == 7 ) {
                put_rn();
            } else if ( pinpos == 15 ) {
                ;
            } else {
                PRINTF(", ");
            }
        }
    }
    put_rn();
    PRINTF( "%s %s", pnmsg5, pnmsg6);
    i = GPIOx->IDR;
    reg_print( SIZE32,i);
    put_rn();
    PRINTF( "%s %s", pnmsg4, pnmsg6);
    i = GPIOx->ODR;
    reg_print( SIZE32,i);
    put_rn();
}
#endif  // USE_PORT

#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
void port_mco1_mco2_set(uint8_t n)
{
    GPIO_TypeDef* GPIOx = 0;
    uint32_t temp = 0x00;

    if (n == 0){    // Just save the original setting
        // PA8 -> MCO_1
        GPIOx = GPIOA;
        reg_save0 = GPIOx->AFR[8 >> 3];
        reg_save1 = GPIOx->MODER;
        reg_save2 = GPIOx->OSPEEDR;
        GPIOx = GPIOC;
        reg_save3 = GPIOx->AFR[9 >> 3];
        reg_save4 = GPIOx->MODER;
        reg_save5 = GPIOx->OSPEEDR;
        reg_save6 = RCC->CFGR;
    } else {
        // PA8 -> MCO_1
        GPIOx = GPIOA;
        temp = ((uint32_t)(GPIO_AF0_MCO) << (((uint32_t)8 & (uint32_t)0x07) * 4)) ;
        GPIOx->AFR[8 >> 3] &= ~((uint32_t)0xf << ((uint32_t)(8 & (uint32_t)0x07) * 4)) ;
        GPIOx->AFR[8 >> 3] |= temp;
        GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (8 * 2));
        GPIOx->MODER |= (0x2 << (8 * 2));
        GPIOx->OSPEEDR |= (0x03 << (8 * 2)); // High speed
        // PC9 -> MCO_2
        GPIOx = GPIOC;
        temp = ((uint32_t)(GPIO_AF0_MCO) << (((uint32_t)9 & (uint32_t)0x07) * 4)) ;
        GPIOx->AFR[9 >> 3] &= ~((uint32_t)0xf << ((uint32_t)(9 & (uint32_t)0x07) * 4)) ;
        GPIOx->AFR[9 >> 3] |= temp;
        GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (9 * 2));
        GPIOx->MODER |= (0x2 << (9 * 2));
        GPIOx->OSPEEDR |= (0x03 << (9 * 2)); // High speed
        // Select output clock source
        RCC->CFGR &= 0x009fffff;
        if (n == 1){
            // MC0_1 output HSE 1/4, MCO_2 output SYSCLK 1/4
            //             MCO2          MCO2PRE       MCO1PRE       MCO1
            RCC->CFGR |= (0x0 << 30) + (0x6 << 27) + (0x6 << 24) + (0x3 << 22);
        } else {
            // MC0_1 output HSE 1/1, MCO_2 output SYSCLK 1/2
            //             MCO2          MCO2PRE       MCO1PRE       MCO1
            RCC->CFGR |= (0x0 << 30) + (0x4 << 27) + (0x0 << 24) + (0x3 << 22);
        }
    }
}

void port_mco1_mco2_recover(void)
{
    GPIO_TypeDef* GPIOx = 0;

    // PA8 -> MCO_1
    GPIOx = GPIOA;
    GPIOx->AFR[8 >> 3] = reg_save0;
    GPIOx->MODER = reg_save1;
    GPIOx->OSPEEDR = reg_save2;
    // PC9 -> MCO_2
    GPIOx = GPIOC;
    GPIOx->AFR[9 >> 3] = reg_save3;
    GPIOx->MODER = reg_save4;
    GPIOx->OSPEEDR = reg_save5;
    // MC0_1 & MCO_2
    RCC->CFGR = reg_save6;
}
#endif      // defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)

#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
void cpu_inf( char *ptr )
{
    uint32_t m1 = 0, m2 = 0, m3 = 0, m4 = 0, m5 = 0;

    switch (*ptr++) {
        case 'f' :  // sc - show system clock frequency
            m1 = RCC->CR;
            PRINTF( "CR       = 0x%08x", m1 );
            put_rn();
            m1 = RCC->PLLCFGR;
            PRINTF( "PLLCFGR  = 0x%08x", m1 );
            put_rn();
            m1 = RCC->CFGR;
            PRINTF( "CFGR     = 0x%08x", m1 );
            put_rn();
            m1 = RCC->CIR;
            PRINTF( "CIR      = 0x%08x", m1 );
            put_rn();
            m1 = RCC->AHB1RSTR;
            PRINTF( "AHB1RSTR = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2RSTR;
            PRINTF( "APB2RSTR = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB1RSTR;
            PRINTF( "APB1RSTR = 0x%08x", m1 );
            put_rn();
            m1 = RCC->AHB1ENR;
            PRINTF( "AHB1ENR  = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2ENR;
            PRINTF( "APB2ENR  = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2LPENR;
            PRINTF( "APB2LPENR= 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB1LPENR;
            PRINTF( "APB1LPENR= 0x%08x", m1 );
            put_rn();
            m1 = RCC->CSR;
            PRINTF( "CSR      = 0x%08x", m1 );
            put_rn();
            PRINTF(cmsg11);
            put_rn();
            m1 = PWR->CR;
            PRINTF( "CR       = 0x%08x", m1 );
            put_rn();
            m1 = PWR->CSR;
            PRINTF( "CSR      = 0x%08x", m1 );
            put_rn();
            put_rn();
        case 'F' :  // sF - show system clock frequency
            m1 = RCC->CFGR & RCC_CFGR_SWS;  /* Get SYSCLK source */
            switch (m1) {
                case 0x00:  // HSI used as system clock
                    PRINTF( "%s, %s%dHz", cmsg2, cmsg1,HSI_VALUE );
                    m2 = HSI_VALUE;
                    break;
                case 0x04:  // HSE used as system clock
                    PRINTF( "%s, %s%dHz", cmsg3, cmsg1, HSE_VALUE );
                    m2 = HSE_VALUE;
                    break;
                case 0x08:  // PLL used as system clock
                    PRINTF("fVCO = fPLL-in x (PLLN/PLLM), fPLL-out = fVCO/PLLP, fUSB-out = fVCO/PLLQ");
                    put_rn();
                    m5 = (RCC->PLLCFGR >> 6) & 0x1ff;   // PLLN
                    m1 = RCC->PLLCFGR & 0x3f;           // PLLM
                    PRINTF( "%s PLLN=%d, PLLM=%d", cmsg4, m5, m1 );
                    put_rn();
                    m3 = (RCC->PLLCFGR >> 22) & 0x1;    // Clock source
                    if (m3 == 0) {
                        // HSI oscillator clock selected as PLL clock source
                        m2 = (HSI_VALUE * (m5 / m1));
                        PRINTF( "%s, RC=%dHz", cmsg2, HSI_VALUE );
                    } else {
                        // HSE selected
                        m2 = (((HSE_VALUE) * m5) / m1);
                        if ((RCC->CR >> 18) & 0x01) {  // check HSEBYP bit
                            // HSE(not Xtal) selected as PLL clock source
                            PRINTF( "Use HSE(not Xtal but External Clock)=%dHz", HSE_VALUE );
                        } else {
                            // HSE(Xtal) selected as PLL clock source
                            PRINTF( "%s, Xtal=%dHz", cmsg3, HSE_VALUE );
                        }
                    }
                    put_rn();
                    PRINTF("PLL/Base   %s%dHz", cmsg1, m2);
                    put_rn();
                    m3 = (RCC->PLLCFGR >> 16) & 0x03;  // PLLP
                    switch (m3) {
                        case 0:
                            m3 = 2;
                            break;
                        case 1:
                            m3 = 4;
                            break;
                        case 2:
                            m3 = 6;
                            break;
                        case 3:
                            m3 = 8;
                            break;
                    }
                    m4 = (RCC->PLLCFGR >> 24) & 0x0f;  // PLLQ
                    PRINTF("%s PLLP=%d, PLLQ=%d", cmsg4, m3, m4);
                    put_rn();
                    PRINTF("PLL/System %s%dHz", cmsg1, m2/m3);
                    put_rn();
                    PRINTF("PLL/USB    %s%dHz", cmsg1, m2/m4);
                    m2 = m2/m4;
                    if ((m2 > USB_FREQ_H) || (m2 <USB_FREQ_L)) {
                        PRINTF(" -> USB Freq. is out of range!");
                    }
                    put_rn();
                    break;
                default:    // Not come here
                    PRINTF( cmsg5 );
                    break;
            }
            put_rn();
            PRINTF( "SYSCLK %s%dHz", cmsg6, HAL_RCC_GetSysClockFreq());
            put_rn();
            PRINTF( "HCLK   %s%dHz", cmsg6, HAL_RCC_GetHCLKFreq());
            put_rn();
            PRINTF( "PCLK1  %s%dHz", cmsg6, HAL_RCC_GetPCLK1Freq());
            put_rn();
            PRINTF( "PCLK2  %s%dHz", cmsg6, HAL_RCC_GetPCLK2Freq());
            put_rn();
            put_rn();
            // Check RTC Clock
            PRINTF("RTC Clock");
            put_rn();
            m1 = (RCC->BDCR >> 8) & 0x03;
            switch (m1) {
                case 0: // no clock
                    PRINTF(cmsg7);
                    break;
                case 1: // LSE
                    PRINTF(cmsg8);
                    break;
                case 2: // LSI
                    PRINTF("%s 17 to 47, typ.32KHz", cmsg9);
                    break;
                case 3: // HSE
                    PRINTF( cmsg10 );
                    m2 = (RCC->PLLCFGR >> 16) & 0x1f;   // RTCPRE
                    m3 = HSE_VALUE / m2;
                    PRINTF("%s%dHz", cmsg6, m3);
                    put_rn();
                    break;
                default:    // Not come here
                    PRINTF(cmsg5);
                    break;
            }
            put_rn();
            put_rn();
            break;
        case 'c' :      // sc - show system CPU information
            m1 = SCB->CPUID;
            m2 = ( m1 >> 24 );
            if ( m2 == 0x41 ) {
                PRINTF( "CPU = ARM " );
            } else {
                PRINTF( "CPU = NOT ARM " );
            }
            m2 = ( m1 >> 4 ) & 0xfff;
            if ( m2 == 0xc24 ) {
                PRINTF( "Cortex-M4" );
            } else {
                PRINTF( "NOT Cortex-M4" );
            }
            put_rn();
            m2 = ( m1 >> 20 ) & 0x0f;
            PRINTF( "Variant:%x", m2 );
            put_rn();
            m2 = m1 & 0x7;
            PRINTF( "Revision:%x", m2 );
            put_rn();
            PRINTF( "CPU ID: 0x%08x", m1 );
            put_rn();
            m1 = DBGMCU->IDCODE;
            PRINTF( "DBG ID: 0x%08x", m1 );
            put_rn();
            // unique ID
            // http://waijung.aimagin.com/index.htm?stm32f4_uidread.htm
            m1 = *(__IO uint32_t *)((uint32_t)0x1FFF7A10);
            PRINTF("Unique device ID(94bits):(1) 0x%08x ", m1);
            m1 = *(__IO uint32_t *)((uint32_t)0x1FFF7A14);
            PRINTF("(2) 0x%08x ", m1);
            m1 = *(__IO uint32_t *)((uint32_t)0x1FFF7A18);
            PRINTF( "(3) 0x%08x", m1 );
            put_rn();
            break;
        case '?' :
        default:
            PRINTF( "sc - System CPU information" );
            put_rn();
            PRINTF( "sf - System Clock" );
            put_rn();
    }
}
#elif defined(TARGET_NUCLEO_L152RE)

static __I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};

void cpu_inf( char *ptr )
{
    uint32_t m1, m2, m3, m4, m5;

    switch (*ptr++) {
        case 'f' :  // sc - show system clock frequency
            m1 = RCC->CR;
            PRINTF( "CR       = 0x%08x", m1 );
            put_rn();
            m1 = RCC->ICSCR;
            PRINTF( "ICSCR    = 0x%08x", m1 );
            put_rn();
            m1 = RCC->CFGR;
            PRINTF( "CFGR     = 0x%08x", m1 );
            put_rn();
            m1 = RCC->CIR;
            PRINTF( "CIR      = 0x%08x", m1 );
            put_rn();
            m1 = RCC->AHBRSTR;
            PRINTF( "AHBRSTR  = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2RSTR;
            PRINTF( "APB2RSTR = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB1RSTR;
            PRINTF( "APB1RSTR = 0x%08x", m1 );
            put_rn();
            m1 = RCC->AHBENR;
            PRINTF( "AHBENR   = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2ENR;
            PRINTF( "APB2ENR  = 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB2LPENR;
            PRINTF( "APB2LPENR= 0x%08x", m1 );
            put_rn();
            m1 = RCC->APB1LPENR;
            PRINTF( "APB1LPENR= 0x%08x", m1 );
            put_rn();
            m1 = RCC->CSR;
            PRINTF( "CSR      = 0x%08x", m1 );
            put_rn();
            PRINTF( cmsg11 );
            put_rn();
            m1 = PWR->CR;
            PRINTF( "CR       = 0x%08x", m1 );
            put_rn();
            m1 = PWR->CSR;
            PRINTF( "CSR      = 0x%08x", m1 );
            put_rn();
            put_rn();
        case 'F' :  // sF - show system clock frequency
            m1 = RCC->CFGR & RCC_CFGR_SWS;  /* Get SYSCLK source */
            switch (m1) {
                case 0x00:  // MSI used as system clock
                    m4 = ( RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13;
                    m2 = (32768 * (1 << (m4 + 1)));
                    PRINTF( "%s, %s%dHz", cmsg0, cmsg1, m2);
                    break;
                case 0x04:  // HSI used as system clock
                    PRINTF( "%s, %s%dHz", cmsg2, cmsg1,HSI_VALUE );
                    m2 = HSI_VALUE;
                    break;
                case 0x08:  // HSE used as system clock
                    PRINTF( "%s, %s%dHz", cmsg3, cmsg1, HSE_VALUE );
                    m2 = HSE_VALUE;
                    break;
                case 0x0C:  // PLL used as system clock
                    // Get PLL clock source and multiplication factor
                    m5 = RCC->CFGR & RCC_CFGR_PLLMUL;
                    m1 = RCC->CFGR & RCC_CFGR_PLLDIV;
                    m5 = PLLMulTable[(m5 >> 18)];
                    m1 = (m1 >> 22) + 1;
                    PRINTF( "%s Mul=%d, Div=%d", cmsg4, m5, m1 );
                    put_rn();
                    m3 = RCC->CFGR & RCC_CFGR_PLLSRC;
                    if ( m3 == 0x00 ) {
                        // HSI oscillator clock selected as PLL clock source
                        m2 = (((HSI_VALUE) * m5) / m1);
                        PRINTF( "%s, RC=%dHz", cmsg2, HSI_VALUE );
                    } else {
                        // HSE selected
                        m2 = (((HSE_VALUE) * m5) / m1);
                        if ((RCC->CR >> 18) & 0x01) {  // check HSEBYP bit
                            // HSE(not Xtal) selected as PLL clock source
                            PRINTF( "Use HSE(not Xtal but External Clock)=%dHz", HSE_VALUE );
                        } else {
                            // HSE(Xtal) selected as PLL clock source
                            PRINTF( "%s, Xtal=%dHz", cmsg3, HSE_VALUE );
                        }
                    }
                    put_rn();
                    PRINTF( "PLL %s%dHz", cmsg1, m2 );
                    put_rn();
                    break;
                default:    // Not come here
                    PRINTF( cmsg5 );
                    break;
            }
            put_rn();
            PRINTF( "SYSCLK %s%dHz", cmsg6, HAL_RCC_GetSysClockFreq() );
            put_rn();
            PRINTF( "HCLK   %s%dHz", cmsg6, HAL_RCC_GetHCLKFreq() );
            put_rn();
            PRINTF( "PCLK1  %s%dHz", cmsg6, HAL_RCC_GetPCLK1Freq() );
            put_rn();
            PRINTF( "PCLK2  %s%dHz", cmsg6, HAL_RCC_GetPCLK2Freq() );
            put_rn();
            put_rn();
            m1 = RCC->CSR & RCC_CSR_RTCSEL;
            // Check RTC & LCD Clock
            PRINTF("RTC/LCD Clock");
            put_rn();
            switch (m1) {
                case RCC_CSR_RTCSEL_NOCLOCK:
                    PRINTF( cmsg7 );
                    break;
                case RCC_CSR_RTCSEL_LSE:
                    PRINTF( cmsg8 );
                    break;
                case RCC_CSR_RTCSEL_LSI:
                    PRINTF("%s 26 to 56, typ.38KHz", cmsg9);
                    break;
                case RCC_CSR_RTCSEL_HSE:
                    PRINTF( cmsg10 );
                    break;
                default:    // Not come here
                    PRINTF( cmsg5 );
                    break;
            }
            put_rn();
            put_rn();
            break;
        case 'c' :      // sc - show system CPU information
            m1 = SCB->CPUID;
            m2 = ( m1 >> 24 );
            if ( m2 == 0x41 ) {
                PRINTF( "CPU = ARM " );
            } else {
                PRINTF( "CPU = NOT ARM " );
            }
            m2 = ( m1 >> 4 ) & 0xfff;
            if ( m2 == 0xc23 ) {
                PRINTF( "Cortex-M3" );
            } else {
                PRINTF( "NOT Cortex-M3" );
            }
            put_rn();
            m2 = ( m1 >> 20 ) & 0x0f;
            PRINTF( "Variant:%x", m2 );
            put_rn();
            m2 = m1 & 0x7;
            PRINTF( "Revision:%x", m2 );
            put_rn();
            PRINTF( "CPU ID: 0x%08x", m1 );
            put_rn();
            m1 = DBGMCU->IDCODE;
            PRINTF( "DBG ID: 0x%08x", m1 );
            put_rn();
            // unique ID
            // http://false.ekta.is/2013/09/stm32-unique-id-register-not-so-unique/
            m1 = *(__IO uint32_t *)((uint32_t)0x1FF80050);
            PRINTF("Unique device ID(94bits):(1) 0x%08x ", m1);
            m1 = *(__IO uint32_t *)((uint32_t)0x1FF80054);
            PRINTF("(2) 0x%08x ", m1);
            m1 = *(__IO uint32_t *)((uint32_t)0x1FF80058);
            PRINTF( "(3) 0x%08x", m1 );
            put_rn();
            break;
        case '?' :
        default:
            PRINTF( "sc - System CPU information" );
            put_rn();
            PRINTF( "sf - System Clock" );
            put_rn();
    }
}
#endif  // Select CPU

//-------------------------------------------------------------------------------------------------
//  Monitor Main Program
//-------------------------------------------------------------------------------------------------
void mon_hw(void)
{
    char *ptr;

    put_r();
    PRINTF("%s [Help:'?' key]", mon_msg);
    put_rn();
    for (;;) {
        put_r();
        PUTC('>');
        ptr = linebuf;
        get_line(ptr, buf_size);
        put_r();
        switch (*ptr++) {
                //-----------------------------------------------------------------------------------------
                //    Memory
                //-----------------------------------------------------------------------------------------
            case 'm' :
#if USE_MEM
                mem_inf(ptr);
                put_rn();
#else
                not_select();
#endif   // USE_MEM
                break;
                //-----------------------------------------------------------------------------------------
                //    Register
                //-----------------------------------------------------------------------------------------
            case 'r' :
                put_r();
                PRINTF(mrmsg0);
                put_rn();
                quitflag = 0;
                for (; quitflag != 0xff;) {
                    PRINTF("r>");
                    ptr = linebuf;
                    get_line(ptr, buf_size);
                    put_r();
                    switch(*ptr++) {
                        case 'u' :
#if USE_UART
                            switch(*ptr++) {
                                case '1' :
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART1);
                                    break;
                                case '2' :
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART2);
                                    break;
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                case '6' :
                                    PRINTF("%s%s6%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART6);
                                    break;
#elif defined(TARGET_NUCLEO_L152RE)
                                case '3' :
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART3);
                                    break;
                                case '5' :
                                    PRINTF("%s%s5%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(UART5);
                                    break;
#endif
                                case '*' :
                                    PRINTF( "%s & UART", mrmsg2 );
                                    put_rn();
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART1);
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART2);
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                    PRINTF("%s%s6%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART6);
#elif defined(TARGET_NUCLEO_L152RE)
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(USART3);
                                    PRINTF("%s%s5%s", mrmsg1,mrmsg2,mrmsg1);
                                    usart_reg(UART5);
#endif
                                    break;
                                case '?' :
                                default:
                                    PRINTF( mrmsg3 );
                                    put_rn();
                            }
#else
                            not_select();
#endif // USE_UART
                            break;
                        case 'i' :
#if USE_I2C
                            switch(*ptr++) {
                                case '1' :
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg4,mrmsg1);
                                    i2c_reg( I2C1 );
                                    break;
                                case '2' :
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg4,mrmsg1);;
                                    i2c_reg( I2C2 );
                                    break;
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                case '3' :
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg4,mrmsg1);;
                                    i2c_reg( I2C3 );
                                    break;
#endif
                                case '*' :
                                    PRINTF(mrmsg4);
                                    put_rn();
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg4,mrmsg1);
                                    i2c_reg( I2C1 );
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg4,mrmsg1);
                                    i2c_reg( I2C2 );
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg4,mrmsg1);;
                                    i2c_reg( I2C3 );
#endif
                                    break;
                                case '?' :
                                default:
                                    PRINTF(mrmsg5);
                                    put_rn();
                            }
#else
                            not_select();
#endif // USE_I2C
                            break;
                        case 's' :
#if USE_SPI
                            switch(*ptr++) {
                                case '1' :
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI1 );
                                    break;
                                case '2' :
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI2 );
                                    break;
                                case '3' :
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI3 );
                                    break;
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                case '4' :
                                    PRINTF("%s%s4%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI4 );
                                    break;
#endif
                                case '*' :
                                    PRINTF(mrmsg6);
                                    put_rn();
                                    PRINTF("%s%s1%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI1 );
                                    PRINTF("%s%s2%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI2 );
                                    PRINTF("%s%s3%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI3 );
#if defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
                                    PRINTF("%s%s4%s", mrmsg1,mrmsg6,mrmsg1);
                                    spi_reg( SPI4 );
#endif
                                    break;
                                case '?' :
                                default:
                                    PRINTF(mrmsg7);
                                    put_rn();
                            }
#else
                            not_select();
#endif // USE_SPI
                            break;
                        case 't' :      //
                            not_yet_impliment();
                            break;
                        case 'a' :      //
                            not_yet_impliment();
                            break;
                        case 'd' :      //
                            not_yet_impliment();
                            break;
                        case 'w' :      //
                            not_yet_impliment();
                            break;
                        case 'l' :        //
                            not_yet_impliment();
                            break;
                        case 'c' :      //
                            not_yet_impliment();
                            break;
                        case 'x' :      //
                            not_yet_impliment();
                            break;
                        case 'y' :      //
                            not_yet_impliment();
                            break;
                        case '?' :
                            PRINTF("u - USART");
                            put_rn();
                            PRINTF("i - I2C");
                            put_rn();
                            PRINTF("s - SPI");
                            put_rn();
                            PRINTF("t - TIMER");
                            put_rn();
                            PRINTF("a - ADC");
                            put_rn();
                            PRINTF("d - DAC");
                            put_rn();
                            PRINTF("l - LDC");
                            put_rn();
                            PRINTF("w - WWDG");
                            put_rn();
                            PRINTF("c - COMP");
                            put_rn();
                            break;
                        case 'q' :        // quit
                            quitflag = 0xff;
                            break;
                        default:
                            PUTC('?');
                            put_rn();
                    }
                }
                PRINTF(mrmsg8);
                put_rn();
                break;
                //-----------------------------------------------------------------------------------------
                //    Port
                //-----------------------------------------------------------------------------------------
            case 'p' :
#if USE_PORT
                put_r();
                PRINTF("Enter port a,b,c,d,e,h & * ? for help");
                put_rn();
                quitflag = 0;
                for (; quitflag != 0xff;) {
                    PRINTF("p>");
                    ptr = linebuf;
                    get_line(ptr, buf_size);
                    put_r();
                    switch(*ptr) {
                        case 'a' :
                        case 'b' :
                        case 'c' :
                        case 'd' :
                        case 'e' :
                        case 'h' :
                            port_inf_one(ptr);
                            break;
                        case '*' :
                            rpt_port();
                            break;
                        case '?' :
                            PRINTF("port a,b,c,d,e,h & *");
                            put_rn();
                            break;
                        case 'q' :        // quit
                            quitflag = 0xff;
                            break;
                        default:
                            PUTC('?');
                            put_rn();
                    }
                }
                PRINTF(mrmsg8);
                put_rn();
#else
                not_select();
#endif // USE_PORT
                break;
                //-----------------------------------------------------------------------------------------
                //    System
                //-----------------------------------------------------------------------------------------
            case 's' :    // System related information
#if USE_SYS
                cpu_inf(ptr);
#else
                not_select();
#endif   // USE_SYS
                break;
                //-----------------------------------------------------------------------------------------
                //    Help
                //-----------------------------------------------------------------------------------------
            case '?' :
                hw_msg_hlp();
                break;
                //-----------------------------------------------------------------------------------------
                //    Return to main routine
                //-----------------------------------------------------------------------------------------
            case 'q' :        // Quit
                put_r();
                PRINTF("Return to monitor");
                put_rn();
                return;
                //-----------------------------------------------------------------------------------------
                //    Special command for DEBUG
                //-----------------------------------------------------------------------------------------
            case 'x' :
                not_yet_impliment();
                break;
                //-----------------------------------------------------------------------------------------
                //    no support
                //-----------------------------------------------------------------------------------------
            default:
                PUTC('?');
                put_rn();
                break;
        }
    }
}
#endif  // defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_L152RE)