GCC 开发 STM32 点灯 串口 程序


最近玩了一阵arduino,转投STM32,不过发现网上大部分程序都涉及一些寄存器知识,新入门都总是云里雾里的,决定写个C语言,寄存器无关的Demo项目。


本项目基于GCC,使用stm32f103rbt6,本人在Mac上编译通过,代码适用于Linux。

下载 http://pan.baidu.com/share/link?shareid=605106&uk=4043729724

arm toolchain 使用  summon-arm-toolchain

//main.c 

#include <libopencm3/stm32/gpio.h>

#include <libopencm3/stm32/f1/flash.h>

#include <libopencm3/stm32/rcc.h>

#include <libopencm3/stm32/usart.h>

void USART1_Init();

void delay(void);


int main(void)

{

    rcc_clock_setup_in_hse_8mhz_out_24mhz();//设置时钟

    rcc_peripheral_enable_clock(&RCC_APB2ENR,RCC_APB2ENR_IOPBEN);//打开PB口时钟

    

    gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ,

                  GPIO_CNF_OUTPUT_PUSHPULL,  GPIO0);//PB0输出 灯接PB0

    

USART1_Init();

    

  while(1)

  {

    gpio_clear(GPIOB,GPIO0);//关灯

delay();

        usart_send(USART1,'a');//串口发送

     gpio_set(GPIOB,GPIO0);//开灯

delay();

usart_send(USART1,'A');

  }

}



void delay(void)

{

    unsigned int i;

    for( i = 0; i <0x3ffff; ++i)

        asm("nop");

}


void USART1_Init(void)

{

    rcc_peripheral_enable_clock(&RCC_APB2ENR,RCC_APB2ENR_USART1EN);//打开串口1时钟

    usart_set_mode(USART1,USART_MODE_TX_RX);

    usart_set_stopbits(USART1,USART_STOPBITS_1);

    usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);

    usart_set_baudrate(USART1,19200);

    usart_enable(USART1);

}

//makefile

EPREFIX=/Users/apple/.gentoo

export PATH := $(EPREFIX)/usr/local/bin:$(PATH)

 

PREFIX  = arm-none-eabi


STM32FLASH=stm32flash

CC      = $(PREFIX)-gcc

LD      = $(PREFIX)-ld -v

AR      = $(PREFIX)-ar

AS      = $(PREFIX)-as

CP      = $(PREFIX)-objcopy

OD      = $(PREFIX)-objdump



STM32LIB=${EPREFIX}/usr/local/arm-none-eabi/lib/libopencm3_stm32f1.a

#STM32LIB=${EPREFIX}/usr/local/arm-none-eabi/lib/libstm32.a

STM32LD=stm32.ld

TTY=/dev/tty.SLAB_USBtoUART


CFLAGS= -DSTM32F1 -I./ -c -fno-common -O0 -mcpu=cortex-m3 -mthumb

LFLAGS  = -T$(STM32LD) -nostartfiles

ODFLAGS = -S


run:clean main

${STM32FLASH} -w main.bin -v -g 0x0 ${TTY}

main:main.o stm32.o

${LD} ${LFLAGS} -o main.elf *.o  ${STM32LIB}

${CP} -Obinary main.elf main.bin

clean:

echo $(PATH)

rm -rf *.o main

    



//stm32.ld 

MEMORY 

        rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K 

        ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 


SECTIONS

{

.text : {

*(.vectors) /* Vector table */

*(.text*) /* Program code */

. = ALIGN(4);

*(.rodata*) /* Read-only data */

. = ALIGN(4);

        _sidata = .;

} >rom


/* C++ Static constructors/destructors, also used for __attribute__

* ((constructor)) and the likes */

.preinit_array : {

. = ALIGN(4);

__preinit_array_start = .;

KEEP (*(.preinit_array))

__preinit_array_end = .;

} >rom

.init_array : {

. = ALIGN(4);

__init_array_start = .;

KEEP (*(SORT(.init_array.*)))

KEEP (*(.init_array))

__init_array_end = .;

} >rom

.fini_array : {

. = ALIGN(4);

__fini_array_start = .;

KEEP (*(.fini_array))

KEEP (*(SORT(.fini_array.*)))

__fini_array_end = .;

} >rom


/*

* Another section used by C++ stuff, appears when using newlib with

* 64bit (long long) printf support

*/

.ARM.extab : {

*(.ARM.extab*)

} >rom

.ARM.exidx : {

__exidx_start = .;

*(.ARM.exidx*)

__exidx_end = .;

} >rom


. = ALIGN(4);

_etext = .;


.data : {

        _sdata = .;

_data = .;

*(.data*) /* Read-write initialized data */

. = ALIGN(4);

_edata = .;

} >ram AT >rom

_data_loadaddr = LOADADDR(.data);


.bss : {

        _sbss = .;

*(.bss*) /* Read-write zero initialized data */

*(COMMON)

. = ALIGN(4);

_ebss = .;

} >ram


/*

* The .eh_frame section appears to be used for C++ exception handling.

* You may need to fix this if you're using C++.

*/

/DISCARD/ : { *(.eh_frame) }


. = ALIGN(4);

end = .;

}


PROVIDE(_estack = ORIGIN(ram) + LENGTH(ram));


//stm32.c  启动代码 本文件从另一项目copy的,适用于些芯片所有项目


/**

 ******************************************************************************

 * @file      startup_stm32f10x_hd.c

 * @author    MCD Application Team

 * @version   V3.0.0

 * @date      04/06/2009

 * @brief     STM32F10x High Density Devices vector table for RIDE7 toolchain.

 *            This module performs:

 *                - Set the initial SP

 *                - Set the initial PC == Reset_Handler,

 *                - Set the vector table entries with the exceptions ISR address,

 *                - Configure external SRAM mounted on STM3210E-EVAL board

 *                  to be used as data memory (optional, to be enabled by user)

 *                - Branches to main in the C library (which eventually

 *                  calls main()).

 *            After Reset the Cortex-M3 processor is in Thread mode,

 *            priority is Privileged, and the Stack is set to Main.

 *******************************************************************************

 * @copy

 *

 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS

 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE

 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY

 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING

 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE

 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.

 *

 * <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>

 */


/* Includes ------------------------------------------------------------------*/

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

#define WEAK __attribute__ ((weak))

#define Initial_spTop      0x20000400


/* Private macro -------------------------------------------------------------*/

extern unsigned long _etext;

/* start address for the initialization values of the .data section.

 defined in linker script */

extern unsigned long _sidata;


/* start address for the .data section. defined in linker script */

extern unsigned long _sdata;


/* end address for the .data section. defined in linker script */

extern unsigned long _edata;


/* start address for the .bss section. defined in linker script */

extern unsigned long _sbss;


/* end address for the .bss section. defined in linker script */

extern unsigned long _ebss;


/* init value for the stack pointer. defined in linker script */

extern void _estack;


/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

void Reset_Handler(void)__attribute__((__interrupt__));

extern int main(void);

void __Init_Data(void);


/******************************************************************************

 *

 * Forward declaration of the default fault handlers.

 *

 *******************************************************************************/

void WEAK Reset_Handler(void);

void WEAK NMI_Handler(void);

void WEAK HardFault_Handler(void);

void WEAK MemManage_Handler(void);

void WEAK BusFault_Handler(void);

void WEAK UsageFault_Handler(void);

void WEAK MemManage_Handler(void);

void WEAK SVC_Handler(void);

void WEAK DebugMon_Handler(void);

void WEAK PendSV_Handler(void);

void WEAK SysTick_Handler(void);


/* External Interrupts */

void WEAK WWDG_IRQHandler(void);

void WEAK PVD_IRQHandler(void);

void WEAK TAMPER_IRQHandler(void);

void WEAK RTC_IRQHandler(void);

void WEAK FLASH_IRQHandler(void);

void WEAK RCC_IRQHandler(void);

void WEAK EXTI0_IRQHandler(void);

void WEAK EXTI1_IRQHandler(void);

void WEAK EXTI2_IRQHandler(void);

void WEAK EXTI3_IRQHandler(void);

void WEAK EXTI4_IRQHandler(void);

void WEAK DMA1_Channel1_IRQHandler(void);

void WEAK DMA1_Channel2_IRQHandler(void);

void WEAK DMA1_Channel3_IRQHandler(void);

void WEAK DMA1_Channel4_IRQHandler(void);

void WEAK DMA1_Channel5_IRQHandler(void);

void WEAK DMA1_Channel6_IRQHandler(void);

void WEAK DMA1_Channel7_IRQHandler(void);

void WEAK ADC1_2_IRQHandler(void);

void WEAK USB_HP_CAN1_TX_IRQHandler(void);

void WEAK USB_LP_CAN1_RX0_IRQHandler(void);

void WEAK CAN1_RX1_IRQHandler(void);

void WEAK CAN1_SCE_IRQHandler(void);

void WEAK EXTI9_5_IRQHandler(void);

void WEAK TIM1_BRK_IRQHandler(void);

void WEAK TIM1_UP_IRQHandler(void);

void WEAK TIM1_TRG_COM_IRQHandler(void);

void WEAK TIM1_CC_IRQHandler(void);

void WEAK TIM2_IRQHandler(void);

void WEAK TIM3_IRQHandler(void);

void WEAK TIM4_IRQHandler(void);

void WEAK I2C1_EV_IRQHandler(void);

void WEAK I2C1_ER_IRQHandler(void);

void WEAK I2C2_EV_IRQHandler(void);

void WEAK I2C2_ER_IRQHandler(void);

void WEAK SPI1_IRQHandler(void);

void WEAK SPI2_IRQHandler(void);

void WEAK USART1_IRQHandler(void);

void WEAK USART2_IRQHandler(void);

void WEAK USART3_IRQHandler(void);

void WEAK EXTI15_10_IRQHandler(void);

void WEAK RTCAlarm_IRQHandler(void);

void WEAK USBWakeUp_IRQHandler(void);

void WEAK TIM8_BRK_IRQHandler(void);

void WEAK TIM8_UP_IRQHandler(void);

void WEAK TIM8_TRG_COM_IRQHandler(void);

void WEAK TIM8_CC_IRQHandler(void);

void WEAK ADC3_IRQHandler(void);

void WEAK FSMC_IRQHandler(void);

void WEAK SDIO_IRQHandler(void);

void WEAK TIM5_IRQHandler(void);

void WEAK SPI3_IRQHandler(void);

void WEAK UART4_IRQHandler(void);

void WEAK UART5_IRQHandler(void);

void WEAK TIM6_IRQHandler(void);

void WEAK TIM7_IRQHandler(void);

void WEAK DMA2_Channel1_IRQHandler(void);

void WEAK DMA2_Channel2_IRQHandler(void);

void WEAK DMA2_Channel3_IRQHandler(void);

void WEAK DMA2_Channel4_5_IRQHandler(void);

void WEAK SystemInit_ExtMemCtl(void);


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

/******************************************************************************

 *

 * The minimal vector table for a Cortex M3.  Note that the proper constructs

 * must be placed on this to ensure that it ends up at physical address

 * 0x0000.0000.

 *

 ******************************************************************************/


__attribute__ ((section(".vectors")))

void (* const g_pfnVectors[])(void) =

{

    (void *)Initial_spTop,     /* The initial stack pointer */

    Reset_Handler,              /* Reset Handler */

    NMI_Handler,                /* NMI Handler */

    HardFault_Handler,          /* Hard Fault Handler */

    MemManage_Handler,          /* MPU Fault Handler */

    BusFault_Handler,           /* Bus Fault Handler */

    UsageFault_Handler,         /* Usage Fault Handler */

    0,                          /* Reserved */

    0,                          /* Reserved */

    0,                          /* Reserved */

    0,                          /* Reserved */

    SVC_Handler,                /* SVCall Handler */

    DebugMon_Handler,           /* Debug Monitor Handler */

    0,                          /* Reserved */

    PendSV_Handler,             /* PendSV Handler */

    SysTick_Handler,            /* SysTick Handler */

    

    /* External Interrupts */

    WWDG_IRQHandler,            /* Window Watchdog */

    PVD_IRQHandler,             /* PVD through EXTI Line detect */

    TAMPER_IRQHandler,          /* Tamper */

    RTC_IRQHandler,             /* RTC */

    FLASH_IRQHandler,           /* Flash */

    RCC_IRQHandler,             /* RCC */

    EXTI0_IRQHandler,           /* EXTI Line 0 */

    EXTI1_IRQHandler,           /* EXTI Line 1 */

    EXTI2_IRQHandler,           /* EXTI Line 2 */

    EXTI3_IRQHandler,           /* EXTI Line 3 */

    EXTI4_IRQHandler,           /* EXTI Line 4 */

    DMA1_Channel1_IRQHandler,   /* DMA1 Channel 1 */

    DMA1_Channel2_IRQHandler,   /* DMA1 Channel 2 */

    DMA1_Channel3_IRQHandler,   /* DMA1 Channel 3 */

    DMA1_Channel4_IRQHandler,   /* DMA1 Channel 4 */

    DMA1_Channel5_IRQHandler,   /* DMA1 Channel 5 */

    DMA1_Channel6_IRQHandler,   /* DMA1 Channel 6 */

    DMA1_Channel7_IRQHandler,   /* DMA1 Channel 7 */

    ADC1_2_IRQHandler,          /* ADC1 & ADC2 */

    USB_HP_CAN1_TX_IRQHandler,  /* USB High Priority or CAN1 TX */

    USB_LP_CAN1_RX0_IRQHandler, /* USB Low  Priority or CAN1 RX0 */

    CAN1_RX1_IRQHandler,        /* CAN1 RX1 */

    CAN1_SCE_IRQHandler,        /* CAN1 SCE */

    EXTI9_5_IRQHandler,         /* EXTI Line 9..5 */

    TIM1_BRK_IRQHandler,        /* TIM1 Break */

    TIM1_UP_IRQHandler,         /* TIM1 Update */

    TIM1_TRG_COM_IRQHandler,    /* TIM1 Trigger and Commutation */

    TIM1_CC_IRQHandler,         /* TIM1 Capture Compare */

    TIM2_IRQHandler,            /* TIM2 */

    TIM3_IRQHandler,            /* TIM3 */

    TIM4_IRQHandler,            /* TIM4 */

    I2C1_EV_IRQHandler,         /* I2C1 Event */

    I2C1_ER_IRQHandler,         /* I2C1 Error */

    I2C2_EV_IRQHandler,         /* I2C2 Event */

    I2C2_ER_IRQHandler,         /* I2C2 Error */

    SPI1_IRQHandler,            /* SPI1 */

    SPI2_IRQHandler,            /* SPI2 */

    USART1_IRQHandler,          /* USART1 */

    USART2_IRQHandler,          /* USART2 */

    USART3_IRQHandler,          /* USART3 */

    EXTI15_10_IRQHandler,       /* EXTI Line 15..10 */

    RTCAlarm_IRQHandler,        /* RTC Alarm through EXTI Line */

    USBWakeUp_IRQHandler,       /* USB Wakeup from suspend */

    TIM8_BRK_IRQHandler,        /* TIM8 Break */

    TIM8_UP_IRQHandler,         /* TIM8 Update */

    TIM8_TRG_COM_IRQHandler,    /* TIM8 Trigger and Commutation */

    TIM8_CC_IRQHandler,         /* TIM8 Capture Compare */

    ADC3_IRQHandler,            /* ADC3 */

    FSMC_IRQHandler,            /* FSMC */

    SDIO_IRQHandler,            /* SDIO */

    TIM5_IRQHandler,            /* TIM5 */

    SPI3_IRQHandler,            /* SPI3 */

    UART4_IRQHandler,           /* UART4 */

    UART5_IRQHandler,           /* UART5 */

    TIM6_IRQHandler,            /* TIM6 */

    TIM7_IRQHandler,            /* TIM7 */

    DMA2_Channel1_IRQHandler,   /* DMA2 Channel 1 */

    DMA2_Channel2_IRQHandler,   /* DMA2 Channel 2 */

    DMA2_Channel3_IRQHandler,   /* DMA2 Channel 3 */

    DMA2_Channel4_5_IRQHandler, /* DMA2 Channel 4 and Channel 5 */

    0,0,0,0,0,0,0,0,           /* @0x130 */

    0,0,0,0,0,0,0,0,           /* @0x150 */

    0,0,0,0,0,0,0,0,           /* @0x170 */

    0,0,0,0,0,0,0,0,           /* @0x190 */

    0,0,0,0,0,0,0,0,           /* @0x1B0 */

    0,0,0,0,                   /* @0x1D0 */

    (void *)0xF1E0F85F         /* @0x1E0. This is for boot in RAM mode for

                                 STM32F10x High Density devices. */

};


/**

 * @brief  This is the code that gets called when the processor first

 *          starts execution following a reset event. Only the absolutely

 *          necessary set is performed, after which the application

 *          supplied main() routine is called.

 * @param  None

 * @retval : None

 */


void Reset_Handler(void)

{

    /* FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is

     required, then adjust the Register Addresses */

    SystemInit_ExtMemCtl();

    

    /* restore original stack pointer */

    asm(" LDR r0, =_estack");

    asm(" MSR msp, r0");

    

    /* Initialize data and bss */

    __Init_Data();

    

    /* Call the application's entry point.*/

    main();

}


/**

 * @brief  initializes data and bss sections

 * @param  None

 * @retval : None

 */


void __Init_Data(void)

{

    unsigned long *pulSrc, *pulDest;

    

    /* Copy the data segment initializers from flash to SRAM */

    pulSrc = &_sidata;

    

    for(pulDest = &_sdata; pulDest < &_edata; )

    {

        *(pulDest++) = *(pulSrc++);

    }

    /* Zero fill the bss segment. */

    for(pulDest = &_sbss; pulDest < &_ebss; )

    {

        *(pulDest++) = 0;

    }

}


/*******************************************************************************

 *

 * Provide weak aliases for each Exception handler to the Default_Handler.

 * As they are weak aliases, any function with the same name will override

 * this definition.

 *

 *******************************************************************************/

#pragma weak NMI_Handler = Default_Handler

#pragma weak MemManage_Handler = Default_Handler

#pragma weak BusFault_Handler = Default_Handler

#pragma weak UsageFault_Handler = Default_Handler

#pragma weak SVC_Handler = Default_Handler

#pragma weak DebugMon_Handler = Default_Handler

#pragma weak PendSV_Handler = Default_Handler

#pragma weak SysTick_Handler = Default_Handler

#pragma weak WWDG_IRQHandler = Default_Handler

#pragma weak PVD_IRQHandler = Default_Handler

#pragma weak TAMPER_IRQHandler = Default_Handler

#pragma weak RTC_IRQHandler = Default_Handler

#pragma weak FLASH_IRQHandler = Default_Handler

#pragma weak RCC_IRQHandler = Default_Handler

#pragma weak EXTI0_IRQHandler = Default_Handler

#pragma weak EXTI1_IRQHandler = Default_Handler

#pragma weak EXTI2_IRQHandler = Default_Handler

#pragma weak EXTI3_IRQHandler = Default_Handler

#pragma weak EXTI4_IRQHandler = Default_Handler

#pragma weak DMA1_Channel1_IRQHandler = Default_Handler

#pragma weak DMA1_Channel2_IRQHandler = Default_Handler

#pragma weak DMA1_Channel3_IRQHandler = Default_Handler

#pragma weak DMA1_Channel4_IRQHandler = Default_Handler

#pragma weak DMA1_Channel5_IRQHandler = Default_Handler

#pragma weak DMA1_Channel6_IRQHandler = Default_Handler

#pragma weak DMA1_Channel7_IRQHandler = Default_Handler

#pragma weak ADC1_2_IRQHandler = Default_Handler

#pragma weak USB_HP_CAN1_TX_IRQHandler = Default_Handler

#pragma weak USB_LP_CAN1_RX0_IRQHandler = Default_Handler

#pragma weak CAN1_RX1_IRQHandler = Default_Handler

#pragma weak CAN1_SCE_IRQHandler = Default_Handler

#pragma weak EXTI9_5_IRQHandler = Default_Handler

#pragma weak TIM1_BRK_IRQHandler = Default_Handler

#pragma weak TIM1_UP_IRQHandler = Default_Handler

#pragma weak TIM1_TRG_COM_IRQHandler = Default_Handler

#pragma weak TIM1_CC_IRQHandler = Default_Handler

#pragma weak TIM2_IRQHandler = Default_Handler

#pragma weak TIM3_IRQHandler = Default_Handler

#pragma weak TIM4_IRQHandler = Default_Handler

#pragma weak I2C1_EV_IRQHandler = Default_Handler

#pragma weak I2C1_ER_IRQHandler = Default_Handler

#pragma weak I2C2_EV_IRQHandler = Default_Handler

#pragma weak I2C2_ER_IRQHandler = Default_Handler

#pragma weak SPI1_IRQHandler = Default_Handler

#pragma weak SPI2_IRQHandler = Default_Handler

#pragma weak USART1_IRQHandler = Default_Handler

#pragma weak USART2_IRQHandler = Default_Handler

#pragma weak USART3_IRQHandler = Default_Handler

#pragma weak EXTI15_10_IRQHandler = Default_Handler

#pragma weak RTCAlarm_IRQHandler = Default_Handler

#pragma weak USBWakeUp_IRQHandler = Default_Handler

#pragma weak TIM8_BRK_IRQHandler = Default_Handler

#pragma weak TIM8_UP_IRQHandler = Default_Handler

#pragma weak TIM8_TRG_COM_IRQHandler = Default_Handler

#pragma weak TIM8_CC_IRQHandler = Default_Handler

#pragma weak ADC3_IRQHandler = Default_Handler

#pragma weak FSMC_IRQHandler = Default_Handler

#pragma weak SDIO_IRQHandler = Default_Handler

#pragma weak TIM5_IRQHandler = Default_Handler

#pragma weak SPI3_IRQHandler = Default_Handler

#pragma weak UART4_IRQHandler = Default_Handler

#pragma weak UART5_IRQHandler = Default_Handler

#pragma weak TIM6_IRQHandler = Default_Handler

#pragma weak TIM7_IRQHandler = Default_Handler

#pragma weak DMA2_Channel1_IRQHandler = Default_Handler

#pragma weak DMA2_Channel2_IRQHandler = Default_Handler

#pragma weak DMA2_Channel3_IRQHandler = Default_Handler

#pragma weak DMA2_Channel4_5_IRQHandler = Default_Handler

#pragma weak SystemInit_ExtMemCtl = SystemInit_ExtMemCtl_Dummy


/**

 * @brief  This is the code that gets called when the processor receives an

 *         unexpected interrupt.  This simply enters an infinite loop, preserving

 *         the system state for examination by a debugger.

 *

 * @param  None

 * @retval : None

 */


void Default_Handler(void)

{

    /* Go into an infinite loop. */

    while (1)

    {

    }

}


/**

 * @brief  Dummy SystemInit_ExtMemCtl function

 * @param  None

 * @retval : None

 */


void SystemInit_ExtMemCtl_Dummy(void)

{

}


/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值