Demostrate PWM driver.

This commit is contained in:
Yilin Sun 2023-04-07 23:54:10 +08:00
parent 3104a44e7c
commit 1aa29457de
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
8 changed files with 115 additions and 348 deletions

12
.clang-format Normal file
View File

@ -0,0 +1,12 @@
BasedOnStyle: Google
IndentWidth: 4
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveDeclarations: Consecutive
AlignConsecutiveAssignments: Consecutive
AllowShortFunctionsOnASingleLine: None
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: false
AfterStruct: false
SplitEmptyFunction: false
ColumnLimit: 120

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/cmake-build-*
/.vscode
/vendor

View File

@ -5,30 +5,19 @@ project(libch57x_hello)
enable_language(CXX)
enable_language(ASM)
# Extra CFlags
set(TARGET_CFLAGS_EXTRA "-Og")
set(TARGET_CFLAGS_EXTRA "-Og")
set(TARGET_LDFLAGS_EXTRA "-Wl,--print-memory-usage")
# Different linker scripts
# Linker scripts
set(TARGET_LDSCRIPT_FLASH "${CMAKE_SOURCE_DIR}/lib/libch57x/lib/CMSIS_Vendor/WCH/CH57x/Source/GCC/ch579_FLASH.ld")
set(TARGET_LDSCRIPT_RAM "${CMAKE_SOURCE_DIR}/ch579_RAM.ld")
# Copy them from Makefile
set(TARGET_C_SOURCES
set(TARGET_SOURCES
"lib/libch57x/lib/CMSIS_Vendor/WCH/CH57x/Source/GCC/startup_ch57x.c"
"src/irq_handlers.c"
"src/main.c"
)
# Copy them from Makefile
set(TARGET_ASM_SOURCES
)
# Copy them from Makefile
set(TARGET_C_DEFINES
)
# Copy them from Makefile
set(TARGET_C_INCLUDES
"include"
)
@ -42,26 +31,23 @@ set(TARGET_LIBS
set(TARGET_LIB_DIRECTORIES
)
# Device specific settings, goes to CFLAGS and LDFLAGS
set(TARGET_CFLAGS_HARDWARE "-mcpu=cortex-m0 -mfloat-abi=soft -mthumb")
# Conditional flags
# DEBUG
set(CMAKE_C_FLAGS_DEBUG "-DDEBUG -Og -g")
set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -Og -g")
set(CMAKE_ASM_FLAGS_DEBUG "-DDEBUG -Og -g")
set(CMAKE_C_FLAGS_DEBUG "-DDEBUG -O0 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -O0 -g")
set(CMAKE_ASM_FLAGS_DEBUG "-DDEBUG -O0 -g")
# RELEASE
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2 -flto")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O2 -flto")
set(CMAKE_ASM_FLAGS_RELEASE "-DNDEBUG -O2 -flto")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-flto")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-flto")
# Final compiler flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_CFLAGS_HARDWARE} ${TARGET_CFLAGS_EXTRA} -Wall -fdata-sections -ffunction-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TARGET_CFLAGS_HARDWARE} ${TARGET_CXXFLAGS_EXTRA} -Wall -fdata-sections -ffunction-sections")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${TARGET_CMAKE_C_FLAGS} -x assembler-with-cpp")
set(CMAKE_EXE_LINKER_FLAGS "-specs=nano.specs -Wl,--gc-sections -lc -lm -lnosys ${TARGET_LDFLAGS_EXTRA}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fno-common -fno-builtin -ffreestanding -fdata-sections -ffunction-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-common -fno-builtin -ffreestanding -fdata-sections -ffunction-sections")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
# Include sub directories here
set(LIBCH57X_DEVICE "CH579")
@ -75,32 +61,25 @@ link_libraries(${TARGET_LIBS})
# Main targets are added here
# **** Internal Flash ****
# Create ELF
add_executable("${CMAKE_PROJECT_NAME}_FLASH.elf" ${TARGET_C_SOURCES} ${TARGET_ASM_SOURCES})
add_executable("${CMAKE_PROJECT_NAME}_FLASH.elf" ${TARGET_SOURCES})
target_compile_definitions("${CMAKE_PROJECT_NAME}_FLASH.elf"
PRIVATE ${TARGET_C_DEFINES_XIP}
)
target_link_options("${CMAKE_PROJECT_NAME}_FLASH.elf"
PRIVATE "-T${TARGET_LDSCRIPT_FLASH}"
PRIVATE "-Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}_FLASH.map,--cref"
)
PRIVATE "-Wl,--Map=${CMAKE_PROJECT_NAME}_FLASH.map"
)
set_property(TARGET "${CMAKE_PROJECT_NAME}_FLASH.elf" APPEND
PROPERTY ADDITIONAL_CLEAN_FILES "${CMAKE_PROJECT_NAME}_FLASH.map"
)
add_custom_command(OUTPUT "${CMAKE_PROJECT_NAME}_FLASH.hex"
COMMAND ${CMAKE_OBJCOPY} "-O" "ihex" "${CMAKE_PROJECT_NAME}_FLASH.elf" "${CMAKE_PROJECT_NAME}_FLASH.hex"
DEPENDS "${CMAKE_PROJECT_NAME}_FLASH.elf"
)
)
add_custom_target("${CMAKE_PROJECT_NAME}_FLASH_HEX" DEPENDS "${CMAKE_PROJECT_NAME}_FLASH.hex")
# **** Internal SRAM ****
# Create ELF
add_executable("${CMAKE_PROJECT_NAME}_RAM.elf" ${TARGET_C_SOURCES} ${TARGET_ASM_SOURCES})
target_link_options("${CMAKE_PROJECT_NAME}_RAM.elf"
PRIVATE "-T${TARGET_LDSCRIPT_RAM}"
PRIVATE "-Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}_RAM.map,--cref"
)
add_custom_command(OUTPUT "${CMAKE_PROJECT_NAME}_RAM.hex"
COMMAND ${CMAKE_OBJCOPY} "-O" "ihex" "${CMAKE_PROJECT_NAME}_FLASH.elf" "${CMAKE_PROJECT_NAME}_RAM.hex"
DEPENDS "${CMAKE_PROJECT_NAME}_RAM.elf"
)
add_custom_target("${CMAKE_PROJECT_NAME}_RAM_HEX" DEPENDS "${CMAKE_PROJECT_NAME}_RAM.hex")
if(DEFINED TARGET_TOOLCHAIN_SIZE)
add_custom_command(TARGET "${CMAKE_PROJECT_NAME}_FLASH.elf" POST_BUILD
COMMAND ${TARGET_TOOLCHAIN_SIZE} "${CMAKE_PROJECT_NAME}_FLASH.elf"
)
endif()

View File

@ -1,4 +1,17 @@
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
# Poor old Windows...
if(WIN32)
set(CMAKE_SYSTEM_NAME "Generic")
endif()
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
# Optionally set size binary name, for elf section size reporting.
set(TARGET_TOOLCHAIN_SIZE arm-none-eabi-size)
set(CMAKE_C_FLAGS_INIT "-mcpu=cortex-m0 -mthumb")
set(CMAKE_CXX_FLAGS_INIT "-mcpu=cortex-m0 -mthumb")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-specs=nano.specs -specs=nosys.specs -Wl,--print-memory-usage -Wl,--no-warn-rwx-segments")
# Make CMake happy about those compilers
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

View File

@ -1,296 +0,0 @@
/******************************************************************************
* @file gcc_arm.ld
* @brief GNU Linker Script for Cortex-M based device
* @version V2.1.0
* @date 04. August 2020
******************************************************************************/
/*
* Copyright (c) 2009-2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*-------- <<< Use Configuration Wizard in Context Menu >>> -------------------
*/
/*---------------------- Flash Configuration ----------------------------------
<h> Flash Configuration
<o0> Flash Base Address <0x0-0xFFFFFFFF:8>
<o1> Flash Size (in Bytes) <0x0-0xFFFFFFFF:8>
</h>
-----------------------------------------------------------------------------*/
__ROM_BASE = 0x00000000;
__ROM_SIZE = 0x0003E800;
/*--------------------- Embedded RAM Configuration ----------------------------
<h> RAM Configuration
<o0> RAM Base Address <0x0-0xFFFFFFFF:8>
<o1> RAM Size (in Bytes) <0x0-0xFFFFFFFF:8>
</h>
-----------------------------------------------------------------------------*/
__RAM_BASE = 0x20000000;
__RAM_SIZE = 0x00008000;
/*--------------------- Stack / Heap Configuration ----------------------------
<h> Stack / Heap Configuration
<o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
<o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
</h>
-----------------------------------------------------------------------------*/
__STACK_SIZE = 0x00000400;
__HEAP_SIZE = 0x00000C00;
/*
*-------------------- <<< end of configuration section >>> -------------------
*/
MEMORY
{
FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE
RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __copy_table_start__
* __copy_table_end__
* __zero_table_start__
* __zero_table_end__
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.vectors))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > RAM
/*
* SG veneers:
* All SG veneers are placed in the special output section .gnu.sgstubs. Its start address
* must be set, either with the command line option <20>--section-start<72> or in a linker script,
* to indicate where to place these veneers in memory.
*/
/*
.gnu.sgstubs :
{
. = ALIGN(32);
} > FLASH
*/
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > RAM
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > RAM
__exidx_end = .;
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG ((__data_end__ - __data_start__) / 4)
/* Add each additional data section here */
/*
LONG (__etext2)
LONG (__data2_start__)
LONG ((__data2_end__ - __data2_start__) / 4)
*/
__copy_table_end__ = .;
} > RAM
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
/* Add each additional bss section here */
/*
LONG (__bss2_start__)
LONG ((__bss2_end__ - __bss2_start__) / 4)
*/
__zero_table_end__ = .;
} > RAM
/**
* Location counter can end up 2byte aligned with narrow Thumb code but
* __etext is assumed by startup code to be the LMA of a section in RAM
* which must be 4byte aligned
*/
__etext = ALIGN (4);
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data)
*(.data.*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
/*
* Secondary data section, optional
*
* Remember to add each additional data section
* to the .copy.table above to asure proper
* initialization during startup.
*/
/*
__etext2 = ALIGN (4);
.data2 : AT (__etext2)
{
. = ALIGN(4);
__data2_start__ = .;
*(.data2)
*(.data2.*)
. = ALIGN(4);
__data2_end__ = .;
} > RAM2
*/
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT > RAM
/*
* Secondary bss section, optional
*
* Remember to add each additional bss section
* to the .zero.table above to asure proper
* initialization during startup.
*/
/*
.bss2 :
{
. = ALIGN(4);
__bss2_start__ = .;
*(.bss2)
*(.bss2.*)
. = ALIGN(4);
__bss2_end__ = .;
} > RAM2 AT > RAM2
*/
.heap (COPY) :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
. = . + __HEAP_SIZE;
. = ALIGN(8);
__HeapLimit = .;
} > RAM
.stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (COPY) :
{
. = ALIGN(8);
__StackLimit = .;
. = . + __STACK_SIZE;
. = ALIGN(8);
__StackTop = .;
} > RAM
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

@ -1 +1 @@
Subproject commit 1140a7cf4202d783875bc9cb61d6cd16d45f0e1b
Subproject commit a0dd13fbf941ad44411294cafe876d517375798d

1
src/irq_handlers.c Normal file
View File

@ -0,0 +1 @@
#include "libch57x.h"

View File

@ -1,9 +1,64 @@
#include "ch57x.h"
#include "libch57x.h"
#define LED_PORT LIBCH57X_GPIO_BANK_B
#define LED_PIN 0U
#define LED_PWM_CH 2U
#define LED_PWM_MASK (1U << LED_PWM_CH)
static volatile uint32_t s_tick_count = 0UL;
static void tick_delay(uint32_t msec) {
uint32_t tick_start = s_tick_count;
while (s_tick_count - tick_start <= msec) {
/* -- */
}
}
int main(int argc, const char *argv[]) {
volatile uint8_t chip_id = CH57x_SYSAUX->CHIP_ID;
SysTick_Config(4000); /* 1kHz */
libch57x_gpio_config_t led_cfg = {
.bank = LED_PORT,
.pin_mask = (1U << LED_PIN),
.mode = LIBCH57X_GPIO_MODE_OUTPUT_5MA,
};
libch57x_gpio_config(&led_cfg);
libch57x_pwm_config_t pwm_cfg = {
.cyc_mode = LIBCH57x_PWM_CYC_MODE_8B,
.cyc_sel = LIBCH57x_PWM_CYCLE_SEL_NORM,
.stag_en = 0U,
};
libch57x_pwm_config(PWM, &pwm_cfg);
libch57x_pwm_clock_div(PWM, 32);
libch57x_pwm_polarity(PWM, LED_PWM_MASK, true);
libch57x_pwm_duty(PWM, LED_PWM_MASK, 4);
libch57x_pwm_enable(PWM, LED_PWM_MASK, true);
uint8_t new_duty = 0;
uint8_t duty_dir = 0;
for (;;) {
// Dead Loop.
tick_delay(10);
if (duty_dir == 0U) {
libch57x_pwm_duty(PWM, LED_PWM_MASK, new_duty++);
if (new_duty == 0) {
duty_dir = 1U;
}
} else {
libch57x_pwm_duty(PWM, LED_PWM_MASK, --new_duty);
if (new_duty == 0) {
duty_dir = 0U;
}
}
}
}
void SysTick_Handler(void) {
s_tick_count++;
}