Compare commits

...

5 commits

Author SHA1 Message Date
jakeg00dwin
5dc658b620 updated test and blink sources 2025-06-06 07:54:49 -07:00
jakeg00dwin
06efeab4e5 automatic fomatting chagnes. 2025-06-06 07:54:05 -07:00
jakeg00dwin
db5dd3784d Added linker line in text section for external object files. 2025-03-29 20:05:49 -07:00
jakeg00dwin
e1bc0ec65a Added line for generate hex formatted output. 2025-03-29 20:05:13 -07:00
jakeg00dwin
77241d1795 Added target properties for making elf files. 2025-03-29 20:02:24 -07:00
12 changed files with 3623 additions and 3463 deletions

View file

@ -22,12 +22,12 @@ endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Request C standard features
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED True)
set(CMAKE_C_FLAGS "-Wall -Wpedantic")
# SETUP THE CXX flags for .cpp
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "-Wall -Werror -Wpedantic")

6700
inc/ch32v003hw.h Executable file → Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
add_executable(${PROJECT_NAME}
main.c
ch32fun.c
#blink/blink.c
)
target_include_directories(${PROJECT_NAME} PUBLIC
@ -9,6 +10,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC
)
target_link_libraries(${PROJECT_NAME} PRIVATE
blink
gcc
)
@ -49,7 +51,14 @@ target_link_options(${PROJECT_NAME} PUBLIC
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
# Convert output to hex and binary
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.hex
)
#add_subdirectory(attic)
add_subdirectory(ADC)
add_subdirectory(RegEdit)
add_subdirectory(blink)

43
src/blink/CMakeLists.txt Normal file
View file

@ -0,0 +1,43 @@
add_library(blink STATIC
blink.c
)
target_include_directories(blink PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
if(NOT UNIT_TESTING)
# The `-ffunction-sections` and `-fdata-sections` need to be used
# in the compile and linker options otherwise it doesnt't
# correctly remove the unused functions.
target_compile_options(blink PUBLIC
-g
-Os
-flto
-ffunction-sections
-fdata-sections
-fmessage-length=0
-msmall-data-limit=8
-march=rv32ec
-mabi=ilp32e
-DCH32V003=1
)
# target_link_options(blink PUBLIC
# -flto
# -ffunction-sections
# -fdata-sections
# -fmessage-length=0
# -msmall-data-limit=8
# -march=rv32ec
# -mabi=ilp32e
# -static-libgcc
# -nostdlib
# -L${CMAKE_SOURCE_DIR}/src
# -Wl,--print-memory-usage
# -Wl,-Map=${PROJECT_NAME}.map
# -Wl,--gc-sections
# -T${CMAKE_SOURCE_DIR}/src/linker_script.ld
# )
endif()

34
src/blink/blink.c Normal file
View file

@ -0,0 +1,34 @@
/*
* Author: username
* Date: 2025
* filename: blink.c
* description: module_purpose
*/
#include "blink.h"
// #include <ch32fun.h>
// Define the function pointer (initialized to NULL)
DelayFunction delay_ms = 0;
// Returns without caling if function pointer wasn't defined.
void blink_led(unsigned int times)
{
if (!delay_ms)
{
return;
}
for (int i = 0; i < times; i++)
{
// Sets the gpio pin(high).
*GPIO_PORT_BSHR |= (1 << 0);
delay_ms(500);
// Resets the gpio pin(low).
*GPIO_PORT_BSHR |= (1 << (0 + 16));
delay_ms(500);
}
}

20
src/blink/blink.h Normal file
View file

@ -0,0 +1,20 @@
/*
* Author: Jake G
* Date: 2025
* filename: BLINK.h
* description: blink LED(for testing.)
*/
#ifndef BLINK_H
#define BLINK_H
#include <stdint.h>
extern volatile uint32_t *GPIO_PORT_BSHR;
typedef void (*DelayFunction)(unsigned int ms);
extern DelayFunction delay_ms;
void blink_led(unsigned int times);
#endif // BLINK_H

View file

@ -1,11 +1,27 @@
/* Entry Point of program, interrupt vector table in this case.*/
/* IVT: data structure that associates list of interrupt handlers with
* a list of interrupt requests in a table of interrupt vectors.
*/
ENTRY( InterruptVector )
/*
* Memory Layout:
* Flash(read execute):
* Ram(read write execute)
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 2K
}
SECTIONS
{
/*
* Initialization section:
* handles startup initialization routines stored in flash.
*/
.init :
{
_sinit = .;
@ -14,6 +30,12 @@ SECTIONS
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
/*
* Text Section:
* Contains executable code and read-only data(rodata)
* Stored in flash.
*/
.text :
{
. = ALIGN(4);
@ -22,15 +44,31 @@ SECTIONS
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
/* Include additional object files. */
/* *(EXTERN(*)) /* Link against external symbols */
. = ALIGN(4);
} >FLASH AT>FLASH
/*
* Finalization Section:
* Contains finalization routines, executed before exiting the program.
*/
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
/*PROVODE: defines a symbol only if it is not already defined elsewhere.*/
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
/*
* The preinit_array and init_array handle static/global constructors and
* initalizers.
*/
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
@ -51,6 +89,8 @@ SECTIONS
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
/* Constructors Section: needed for C++ */
.ctors :
{
KEEP (*crtbegin.o(.ctors))
@ -59,6 +99,8 @@ SECTIONS
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
/* Destructors Section: needed for C++ */
.dtors :
{
KEEP (*crtbegin.o(.dtors))
@ -67,16 +109,27 @@ SECTIONS
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
/* Likely for data alignment.*/
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
/* Likely for dynamic loader alignment.*/
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
/*
* Data section: Initialized Variables
* contains initialized variables copied from flash to ram at startup.
* `_sdata` and `_edata` mark the start and end of the `.data` section.
*/
.data :
{
. = ALIGN(4);
@ -94,9 +147,21 @@ SECTIONS
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
/* Trying to include datasections for external object files.*/
/*
* *(.data)
* *(.data.*)
*/
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
/* BSS Section: Contains uninitialized variables.
* Holds uninited global/static vars. The runtime must zero out this
* section before main function.
*/
.bss :
{
. = ALIGN(4);

View file

@ -1,43 +1,54 @@
#include "ch32fun.h"
#include <blink.h>
#include <stdio.h>
#define ADC_BUFFER_SIZE 32
//globals
// external defines.
volatile uint32_t *GPIO_PORT_BSHR = &GPIOD->BSHR;
// globals
volatile uint16_t adc_buffer[ADC_BUFFER_SIZE] = {0};
volatile uint16_t avg = 0;
volatile uint16_t avg = 0;
//Function Prototypes.
void ADC_DMA_Init(void);
// Function Prototypes.
void ADC_DMA_Init(void);
void GPIO_Init(void);
void DMA_Init(void);
void ADC_Init(void);
void GPIO_Init(void);
void DMA_Init(void);
void ADC_Init(void);
uint16_t ADC_Read(void) {
//while (!(ADC1->STATR & ADC_FLAG_EOC)); // Wait for conversion to complete
uint16_t ADC_Read(void)
{
// while (!(ADC1->STATR & ADC_FLAG_EOC)); // Wait for conversion to complete
return ADC1->RDATAR; // Return ADC value
}
int main(void)
{
SystemInit();
printf("DMA ADC TESTING\r\n");
DMA_Init();
GPIO_Init();
ADC_Init();
GPIO_Init();
ADC_Init();
// set delay fp.
// delay_ms = Delay_Ms;
blink_led(5);
uint16_t old_value = UINT16_MAX;
printf("DMA_Channel1->CNTR: %d\r\n", (uint16_t)DMA1_Channel1->CNTR);
if(!(ADC1->STATR & ADC_FLAG_EOC)){
if (!(ADC1->STATR & ADC_FLAG_EOC))
{
printf("ADC1 Status register EOC: False\r\n");
}
if(!(DMA1_Channel1->CFGR & DMA_CFGR1_EN)){
if (!(DMA1_Channel1->CFGR & DMA_CFGR1_EN))
{
printf("DMA1 Channel1 isn't enabled!\r\n");
}
@ -50,24 +61,27 @@ int main(void)
}
*/
while(1){
while (1)
{
printf("ADC_BUFFER: ");
for(int i = 0; i < ADC_BUFFER_SIZE; i++){
printf("%d ", adc_buffer[i]);
for (int i = 0; i < ADC_BUFFER_SIZE; i++)
{
printf("%d ", adc_buffer[i]);
}
printf("\r\n");
}
while(1){
//printf("ADC reading: %d\r\n", avg);
//Delay_Ms(1000);
if(avg != old_value){
while (1)
{
// printf("ADC reading: %d\r\n", avg);
// Delay_Ms(1000);
if (avg != old_value)
{
old_value = avg;
printf("ADC reading: %d\r\n", avg);
Delay_Ms(500);
}
}
}
void GPIO_Init(void)
@ -76,14 +90,12 @@ void GPIO_Init(void)
// Enable the clock for the GPIO port it's on
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
// Configure the GPIO pin C4 as analog input. bits[19:16]
// CFN(config): Analog, Mode: Input
GPIOC->CFGLR &= ~(0xf<<(4*4));
GPIOC->CFGLR &= ~(0xf << (4 * 4));
}
void ADC_Init(void)
{
printf("ADC_Init()\r\n");
@ -95,44 +107,43 @@ void ADC_Init(void)
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1;
RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1;
//I don't change the prescaler, because I'm not using an external crystal.
//RCC->CFGR |= (0x1F<<11); //Sets the prescaler for div128.
// I don't change the prescaler, because I'm not using an external crystal.
// RCC->CFGR |= (0x1F<<11); //Sets the prescaler for div128.
// Enable ADC scanning
ADC1->CTLR1 |= ADC_SCAN;
ADC1->CTLR1 |= ADC_SCAN;
// Configure the ADC
// Configure the ADC
// -- Set the ADON bit.
ADC1->CTLR2 |= (1<<0);
ADC1->CTLR2 |= (1 << 0);
// -- Set the External selection to SWSTART
ADC1->CTLR2 |= ADC_EXTSEL;
// -- Enable DMA for the ADC DMA_Enable --> bit8
ADC1->CTLR2 |= (1<<8);
ADC1->CTLR2 |= (1 << 8);
// -- Set the ADC conversion for continuous
ADC1->CTLR2 |= (1<<1);
ADC1->CTLR2 |= (1 << 1);
// -- Set ADC sample time. 3 offset, channel 2
// Sets the sampling to 3 cycles.
ADC1->SAMPTR2 &= ~(0xf<<(3*2));
ADC1->SAMPTR2 &= ~(0xf << (3 * 2));
// Select ADC channel
ADC1->RSQR1 = 0; // RSQR1 L num ch conversions = 1
ADC1->RSQR2 = 0;
ADC1->RSQR1 = 0; // RSQR1 L num ch conversions = 1
ADC1->RSQR2 = 0;
ADC1->RSQR3 = 2;
// Start ADC conversion SWSTART bit 22
ADC1->CTLR2 |= (1<<22);
ADC1->CTLR2 |= (1 << 22);
}
void DMA_Init(void)
{
//NOTE: Most of this could be a single line for the CFGR but this is more
//explicit.
//NOTE: See page 66 in the RM for figuring out the needed DMA channel.
// NOTE: Most of this could be a single line for the CFGR but this is more
// explicit.
// NOTE: See page 66 in the RM for figuring out the needed DMA channel.
printf("DMA_Init()\r\n");
@ -149,54 +160,54 @@ void DMA_Init(void)
DMA1_Channel1->CNTR = ADC_BUFFER_SIZE;
// Set the DMA channel priority, bits[13:12]
DMA1_Channel1->CFGR = 0; //clear it.
DMA1_Channel2->CFGR &= ~((1<<12)|(1<<13)); //sets PL to low
DMA1_Channel1->CFGR = 0; // clear it.
DMA1_Channel2->CFGR &= ~((1 << 12) | (1 << 13)); // sets PL to low
// Set the direction of data transfer, mode and datawidth for src & dst
// along with th, tc and te interrupt enable bits.
// Set the mem2mem as false.
DMA1_Channel1->CFGR &= ~(1<<14);
DMA1_Channel1->CFGR &= ~(1 << 14);
// Set dir as Peripheral to memory.
DMA1_Channel1->CFGR &= ~(1<<4);
DMA1_Channel1->CFGR &= ~(1 << 4);
// Set the datawidth for source and destination as 16bits.
//DMA1_Channel1->CFGR |= (1<<10);
//DMA1_Channel1->CFGR |= (1<<8);
// DMA1_Channel1->CFGR |= (1<<10);
// DMA1_Channel1->CFGR |= (1<<8);
DMA1_Channel1->CFGR |= DMA_PeripheralDataSize_HalfWord;
DMA1_Channel1->CFGR |= DMA_MemoryDataSize_HalfWord;
// Set circular mode.
DMA1_Channel1->CFGR |= (1<<5);
DMA1_Channel1->CFGR |= (1 << 5);
// Enable memory address increment.
DMA1_Channel1->CFGR |= (1<<7);
DMA1_Channel1->CFGR |= (1 << 7);
//Enable IRQ
//NVIC_EnableIRQ(DMA1_Channel1_IRQn);
// Enable IRQ
// NVIC_EnableIRQ(DMA1_Channel1_IRQn);
// Set the transfer complete interrupt.
DMA1_Channel1->CFGR |= (1<<1);
DMA1_Channel1->CFGR |= (1 << 1);
// Set the enable bit in DMA_CCRx register to start channel x
DMA1_Channel1->CFGR |= (1<<0);
DMA1_Channel1->CFGR |= (1 << 0);
}
void DMA1_Channel1_IRQHandler(void) __attribute__((interrupt));
void DMA1_Channel1_IRQHandler()
{
if(DMA1->INTFR & DMA1_FLAG_TC1) {
if (DMA1->INTFR & DMA1_FLAG_TC1)
{
DMA1->INTFCR = DMA_CTCIF1;
printf("DMA ISR!\r\n");
//current_write_buffer = current_read_buffer;
// current_write_buffer = current_read_buffer;
avg = 0;
for(int i = 0; i < ADC_BUFFER_SIZE; i++){
for (int i = 0; i < ADC_BUFFER_SIZE; i++)
{
avg += adc_buffer[i];
}
//Divide it by 32
// Divide it by 32
avg = avg >> 5;
DMA_Init();
}

View file

@ -5,6 +5,7 @@
IMPORT_TEST_GROUP(simple_test);
IMPORT_TEST_GROUP(test_ADC);
IMPORT_TEST_GROUP(test_RegEdit);
IMPORT_TEST_GROUP(test_blink);
//START: main
int main(int argc, char** argv)

View file

@ -1,6 +1,7 @@
project(Tests)
# TEST_DIRS
add_subdirectory(blink)
add_subdirectory(MockRegEdit)
add_subdirectory(RegEdit)
add_subdirectory(simple_test)
@ -19,6 +20,7 @@ target_link_libraries(AllTests
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
# TEST_LINKS
test_blink
test_ADC
test_RegEdit
simple_test

View file

@ -0,0 +1,10 @@
# TEST_RUNNER
add_library(test_blink
test_blink.cpp
)
target_link_libraries(test_blink
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
blink
)

View file

@ -0,0 +1,61 @@
/*
* Author: username
* Date: todays_date
* filename: test_blink.c
* description: module_purpose
*/
#include "CppUTest/CommandLineTestRunner.h"
extern "C"
{
#include "blink.h"
}
volatile uint32_t fake_bshr_reg = 0;
volatile uint32_t* GPIO_PORT_BSHR = &fake_bshr_reg;
unsigned int called;
void fake_delay(unsigned int ms)
{
called += 1;
return;
}
TEST_GROUP(test_blink)
{
void setup()
{
fake_bshr_reg = 0;
called = 0;
}
void teardown()
{
}
};
TEST(test_blink, UninitializedFuncPointer)
{
blink_led(5);
CHECK_EQUAL(0, fake_bshr_reg);
}
TEST(test_blink, BlinkChangesReg)
{
//Set the function pointer.
delay_ms = fake_delay;
blink_led(1);
CHECK_EQUAL_TEXT(2, called, "Delay function not called expeced number of times");
CHECK(fake_bshr_reg & (1<<0));
CHECK(fake_bshr_reg & (1<<(0+16)));
//Unset function pointer
delay_ms = 0;
}