Compare commits

..

9 commits

38 changed files with 3223 additions and 1718 deletions

View file

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

View file

@ -68,4 +68,5 @@ instructions.
- [ ] Add useful mock examples. - [ ] Add useful mock examples.
- [X] Get Blinky to run on hardware. - [X] Get Blinky to run on hardware.
- [ ] Set conditional compile/linker flags? - [ ] Set conditional compile/linker flags?
- [ ] Get RegEdit setup for 32bit addresses.

71
inc/RegEdit.h Normal file
View file

@ -0,0 +1,71 @@
/**
* @brief Module/Interface for editing AVR registers
* @details This file is an interface to AVR registers or the avr/io.h
* @author Jake G
* @date 2024
* @copyright None
* @file RegEdit.h
*/
#ifndef REGEDIT_H
#define REGEDIT_H
#include <stdint.h>
#include <stdbool.h>
/**
* @brief Sets the value of the register to 0xFF.
* @param reg A pointer to a register
*/
void RegEdit_SetRegister(void *reg);
/**
* @brief Sets the value of the register to 0x00.
* @param reg A pointer to a register
*/
void RegEdit_ClearRegister(void *reg);
/**
* @brief Sets a single bit in the register.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
void RegEdit_SetBit(void *reg, uint8_t bit_num);
/**
* @brief Clears a single bit in the register.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
void RegEdit_ClearBit(void *reg, uint8_t bit_num);
/**
* @brief Checks if a single bit is set in the register.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num);
/**
* @brief Preforms logical OR Equals with the passed num.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
void RegEdit_OR_Num(void *reg, uint8_t num);
/**
* @brief Preforms logical AND Equals with the passed num.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
void RegEdit_AND_Num(void *reg, uint8_t num);
/**
* @brief Sets the register to the passed number value.
* @param reg A pointer to a register
* @param The bit's index or number in the register
*/
void RegEdit_SetNum(void *reg, uint8_t num);
#endif //REGEDIT_H

View file

@ -1,4 +1,6 @@
add_subdirectory(MockRegEdit)
add_subdirectory(MockADC)
add_subdirectory(TimerMock)

View file

@ -0,0 +1,7 @@
add_library(MockADC STATIC
MockADC.c
)
target_include_directories(MockADC PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

84
mocks/MockADC/MockADC.c Normal file
View file

@ -0,0 +1,84 @@
/*
* Author: username
* Date: 2024
* filename: MockADC.c
* description: module_purpose
*/
#include "MockADC.h"
#include "CppUTestExt/MockSupport_c.h"
#define FAKESIZE 256
uint16_t fake_data[FAKESIZE];
int fake_index = 0;
static bool is_setup = false;
void ADC_SetPin(uint8_t pin_num)
{
return;
}
void ADC_Setup(void)
{
is_setup = true;
return;
}
void ADC_Init(uint8_t pin_num)
{
mock_c()->actualCall("ADC_Init")
->withUnsignedIntParameters("pin_num", pin_num);
}
void ADC_Enable(void)
{
mock_c()->actualCall("ADC_Enable");
}
void ADC_Disable()
{
mock_c()->actualCall("ADC_Disable");
}
uint16_t ADC_ReadValue_Impl(uint8_t pin_num)
{
mock_c()->actualCall("ADC_ReadValue_Impl")
->withUnsignedIntParameters("pin_num", pin_num);
if(fake_index == 0){
return 0;
}
return fake_data[--fake_index];
}
uint16_t (*ADC_ReadValue)(uint8_t pin_num) = ADC_ReadValue_Impl;
void MockADC_PushValue(uint16_t value){
if(fake_index >= FAKESIZE - 1){
return;
}
fake_data[fake_index++] = value;
}
void MockADC_ZeroIndex(void)
{
fake_index = 0;
}
int MockADC_GetIndex(void)
{
return fake_index;
}
bool MockADC_IsSetup(void)
{
return is_setup;
}

30
mocks/MockADC/MockADC.h Normal file
View file

@ -0,0 +1,30 @@
/**
* @brief PUT_TEXT_HERE
* @details This file is...
* @author username
* @date todays_date
* @copyright None
* @file MOCKADC.h
*/
#ifndef MOCKADC_H
#define MOCKADC_H
#include <stdint.h>
#include <stdbool.h>
void ADC_Setup(void);
void ADC_SetPin(uint8_t pin_num);
void ADC_Init(uint8_t pin_num);
void ADC_Enable(void);
void ADC_Disable(void);
extern uint16_t (*ADC_ReadValue)(uint8_t pin_num);
void MockADC_PushValue(uint16_t value);
void MockADC_ZeroIndex(void);
int MockADC_GetIndex(void);
bool MockADC_IsSetup(void);
#endif //MOCKADC_H

View file

@ -0,0 +1,12 @@
add_library(MockRegEdit STATIC
MockRegEdit.c
)
target_include_directories(MockRegEdit PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(MockRegEdit
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
)

View file

@ -0,0 +1,85 @@
/*
* Author: username
* Date: 2024
* filename: MockRegEdit.c
* description: module_purpose
*/
#include "MockRegEdit.h"
#include "CppUTestExt/MockSupport_c.h"
void RegEdit_SetRegister(void *reg)
{
mock_c()->actualCall("RegEdit_SetRegister")
->withPointerParameters("reg", reg);
}
void RegEdit_ClearRegister(void *reg)
{
mock_c()->actualCall("RegEdit_ClearRegister")
->withPointerParameters("reg", reg);
}
void RegEdit_SetBit(void *reg, uint8_t bit_num)
{
mock_c()->actualCall("RegEdit_SetBit")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("bit_num", bit_num);
}
void RegEdit_ClearBit(void *reg, uint8_t bit_num)
{
mock_c()->actualCall("RegEdit_ClearBit")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("bit_num", bit_num);
}
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num)
{
return mock_c()->actualCall("RegEdit_IsBitSet")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("bit_num", bit_num)
->returnBoolValueOrDefault(true);
//return mock_c()->returnBoolValueOrDefault(true);
}
void RegEdit_OR_Num(void *reg, uint32_t num)
{
mock_c()->actualCall("RegEdit_OR_Num")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("num", num);
}
void RegEdit_AND_Num(void *reg, uint32_t num)
{
mock_c()->actualCall("RegEdit_AND_Num")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("num", num);
}
void RegEdit_SetNum(void *reg, uint32_t num)
{
mock_c()->actualCall("RegEdit_SetNum")
->withPointerParameters("reg", reg)
->withUnsignedIntParameters("num", num);
}
uint8_t RegEdit_ReadReg(void *reg)
{
uint8_t value = *(uint8_t *)reg;
mock_c()->actualCall("RegEdit_ReadReg")
->withPointerParameters("reg", reg)
->returnUnsignedIntValueOrDefault(value);
return value;
}

View file

@ -0,0 +1,30 @@
/**
* @brief PUT_TEXT_HERE
* @details This file is...
* @author username
* @date todays_date
* @copyright None
* @file MockRegEdit.h
*/
#ifndef MOCKREGEDIT_H
#define MOCKREGEDIT_H
#include <stdint.h>
#include <stdbool.h>
void RegEdit_SetRegister(void *reg);
void RegEdit_ClearRegister(void *reg);
void RegEdit_SetBit(void *reg, uint8_t bit_num);
void RegEdit_ClearBit(void *reg, uint8_t bit_num);
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num);
void RegEdit_OR_Num(void *reg, uint32_t num);
void RegEdit_AND_Num(void *reg, uint32_t num);
void RegEdit_SetNum(void *reg, uint32_t num);
uint8_t RegEdit_ReadReg(void *reg);
#endif //MOCKREGEDIT_H

View file

@ -0,0 +1,51 @@
#include "u8_comparator.hpp"
#include "CppUTest/SimpleString.h"
/*
class MyTypeComparator : public MockNamedValueComparator
{
public:
virtual bool isEqual(const void* object1, const void* object2)
{
return object1 == object2;
}
virtual SimpleString valueToString(const void* object)
{
return StringFrom(object);
}
};
*/
bool UInt8PointerComparator::isEqual(const void* object1, const void* object2) {
const uint8_t* ptr1 = reinterpret_cast<const uint8_t*>(object1);
const uint8_t* ptr2 = reinterpret_cast<const uint8_t*>(object2);
return std::memcmp(ptr1, ptr2, sizeof(uint8_t)) == 0;
}
SimpleString UInt8PointerComparator::valueToString(const void* object) {
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(object);
return StringFromFormat("0x%02x", *ptr);
}
/*
bool UInt8PointerComparator::isEqual(const void* object1, const void* object2) const {
const uint8_t* ptr1 = static_cast<const uint8_t*>(object1);
const uint8_t* ptr2 = static_cast<const uint8_t*>(object2);
return std::memcmp(ptr1, ptr2, sizeof(uint8_t)) == 0;
}
SimpleString UInt8PointerComparator::valueToString(const void* object) const {
const uint8_t* ptr = static_cast<const uint8_t*>(object);
return StringFromFormat("0x%02x", *ptr);
}
*/
bool UInt8Comparator::isEqual(const void* object1, const void* object2) {
return (uint8_t*)object1 == (uint8_t *)object2;
}
SimpleString UInt8Comparator::valueToString(const void* object) {
//uint8_t value = reinterpret_cast<uint8_t>(object);
const uint8_t *ptr = reinterpret_cast<const uint8_t*>(object);
return StringFromFormat("0x%02x", *ptr);
}

View file

@ -0,0 +1,20 @@
#ifndef U8_COMPARATOR_H
#define U8_COMPARATOR_H
#include <cstdint>
#include <cstring>
#include <CppUTestExt/MockSupport.h>
class UInt8PointerComparator : public MockNamedValueComparator {
public:
virtual bool isEqual(const void* object1, const void* object2) override;
SimpleString valueToString(const void* object) override;
};
class UInt8Comparator : public MockNamedValueComparator {
public:
virtual bool isEqual(const void* object1, const void* object2) override;
SimpleString valueToString(const void* object) override;
};
#endif //U8_COMPARATOR_H

View file

@ -0,0 +1,7 @@
add_library(TimerMock STATIC
TimerMock.c
)
target_include_directories(TimerMock PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

View file

@ -0,0 +1,31 @@
/*
* Author: Jake G
* Date: 2024-09-02
* filename: TimerMock.c
* description: mocks timers
*/
#include "TimerMock.h"
#include <stdbool.h>
#include "CppUTestExt/MockSupport_c.h"
static bool timer_started = false;
void Timer_Start(void)
{
mock_c()->actualCall("Timer_Start");
timer_started = true;
}
void Timer_Stop(void)
{
mock_c()->actualCall("Timer_Stop");
timer_started = false;
}
uint16_t Timer_GetOverflowCount(void)
{
uint16_t time = 0xAAAA;
return mock_c()->actualCall("Timer_GetOverflowCount")
->returnUnsignedIntValueOrDefault(time);
}

View file

@ -0,0 +1,26 @@
/**
* @brief A Mock of the timer module.
* @details This file is only used for testing.
* @author Jake G
* @date 2024-09-02
* @copyright None
* @file TimerMock.h
*/
#ifndef TIMER_MOCK_H
#define TIMER_MOCK_H
#include <stdint.h>
/**
* A function
* @param a The first argument
*/
void Timer_Start(void);
void Timer_Stop(void);
uint16_t Timer_GetOverflowCount(void);
#endif //TIMER_MOCK_H

View file

@ -28,9 +28,9 @@ format_source_code () {
add_compile_commands () { add_compile_commands () {
if [ -f ./compile_commands.json ]; then if [ -f ./compile_commands.json ]; then
echo "compile_commands.json already exists!\n" echo "compile_commands.json already exists!"
else else
echo "Creating new symlink for compile commands!\n" echo "Creating new symlink for compile commands!"
ln -s ./build/compile_commands.json ./compile_commands.json ln -s ./build/compile_commands.json ./compile_commands.json
fi fi
} }
@ -247,8 +247,8 @@ build_hex () {
CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${WCH_TC}" CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${WCH_TC}"
cmake ${CMAKE_ARGS} ../ cmake ${CMAKE_ARGS} ../
make all make main
make hex #make hex
} }
build_hex_optimized () { build_hex_optimized () {

View file

@ -25,6 +25,9 @@ set(DEBUG_BINARY 1)
set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_VERSION 1)
# Without this flag, CMake is unable to pass the test compilation check
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# This logic checks the operating system. # This logic checks the operating system.
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD") if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD")
@ -32,6 +35,7 @@ if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "FreeBSD")
set(NEWLIB /usr/local/riscv/riscv32-unknown-elf/include) set(NEWLIB /usr/local/riscv/riscv32-unknown-elf/include)
set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc) set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc)
set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++) set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++)
set(CMAKE_ASM_COMPILER riscv32-unknown-elf-gcc)
set(CMAKE_FIND_ROOT_PATH /usr/local/riscv/) set(CMAKE_FIND_ROOT_PATH /usr/local/riscv/)
# Without these two lines it freaks out. # Without these two lines it freaks out.
@ -43,6 +47,7 @@ elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
set(NEWLIB /opt/riscv/riscv32-unknown-elf/include) set(NEWLIB /opt/riscv/riscv32-unknown-elf/include)
set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc) set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc)
set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++) set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++)
set(CMAKE_ASM_COMPILER riscv32-unknown-elf-gcc)
# Without these two lines it freaks out. # Without these two lines it freaks out.
set(CMAKE_C_STANDARD_COMPUTED_DEFAULT GNU) set(CMAKE_C_STANDARD_COMPUTED_DEFAULT GNU)
@ -111,10 +116,13 @@ set(C_FLAGS_ARCH "\
# They print out from the messages just fine, but they are ignored. # They print out from the messages just fine, but they are ignored.
UNSET(CMAKE_C_FLAGS CACHE) UNSET(CMAKE_C_FLAGS CACHE)
UNSET(CMAKE_CXX_FLAGS CACHE)
# I'm appending to the existing cflags from the cmake file in the root dir. # I'm appending to the existing cflags from the cmake file in the root dir.
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}")
#set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}")
set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS} ${C_FLAGS_ARCH} ${OBJECT_GEN_FLAGS}" CACHE STRING "" FORCE)
#------------------- #-------------------

77
src/ADC/ADC.c Normal file
View file

@ -0,0 +1,77 @@
/*
* Author: username
* Date: 2024
* filename: ADC.c
* description: module_purpose
*/
#include "ADC.h"
#include "RegEdit.h"
#include "ch32fun.h"
#define MAX_PIN_NUM 7
static bool IsInvalidPin(uint8_t pin_num)
{
if (pin_num > MAX_PIN_NUM)
{
return true;
}
return false;
}
void ADC_Setup(void)
{
}
void ADC_Init(uint8_t pin_num)
{
if (IsInvalidPin(pin_num))
{
return;
}
}
void ADC_Enable(void)
{
// Set the enable bit in the CTRLA register
// RegEdit_SetBit((void *)&ADC0.CTRLA, 0);
}
void ADC_Disable(void)
{
// Clear the enable ADC flag
// RegEdit_ClearBit((void *)&ADC0.CTRLA, 0);
}
void ADC_SetPin(uint8_t pin_num)
{
if (IsInvalidPin(pin_num))
{
return;
}
// RegEdit_ClearRegister((void *)&ADC0.MUXPOS);
// RegEdit_SetNum((void *)&ADC0.MUXPOS, pin_num);
}
uint16_t ADC_ReadValue_Impl(uint8_t pin_num)
{
// RegEdit_SetNum((void *)&ADC0.COMMAND, ADC_STCONV_bm);
/* Wait until ADC conversion done */
// while (!(ADC0.INTFLAGS & ADC_RESRDY_bm))
//{
// ;
// }
/* Clear the interrupt flag by writing 1: */
// ADC0.INTFLAGS = ADC_RESRDY_bm;
// uint16_t adc_val = (uint16_t)ADC0.RES;
// adc_val = adc_val >> 5;
uint16_t adc_val = 0;
return adc_val;
}
// Set the default for the function pointer.
uint16_t (*ADC_ReadValue)(uint8_t pin_num) = ADC_ReadValue_Impl;

68
src/ADC/ADC.h Normal file
View file

@ -0,0 +1,68 @@
/**
* @brief Interface to the AVR ADC hardware.
* @details This file is...
* @author Jake G
* @date 2024
* @copyright None
* @file ADC.h
*/
#ifndef ADC_H
#define ADC_H
#include <stdbool.h>
#include <stdint.h>
/**
* @brief Initializes the AVR hardware in order to accept
* Input for ADC usage.
* @param pin_num The number of the pin 0-7 you are initializing.
*
* This function only makes use of PORTA by default. It sets the direction
* register to input, disables the pull-up resistor and also diables interrupts
* alongside the input buffer(digital).
*
* This in turn helps reduce noise when using the ADC.
*
*/
void ADC_Init(uint8_t pin_num);
/**
* @brief Enables the ADC
*/
void ADC_Enable(void);
/**
* @brief Disables the ADC
*/
void ADC_Disable();
/**
* @brief Reads ADC value into variable
*
* @param pin_num The bin number of the ADC pin being read.
*
* This function depends on the ADC already being initialized and enabled
* before being called.
*/
extern uint16_t (*ADC_ReadValue)(uint8_t pin_num);
/**
* @brief Sets up the ADC
*
* This function sets up the ADC to take and accumulate 32 samples. It also
* sets the inital delay to 32 ADC clock cycles, and sets the VREF to VDD or
* VCC.
*
* This function should only need to be called once.
*/
void ADC_Setup(void);
/**
* @brief Sets the pin used in the MUX for ADC0.
*
* @param pin_num The number of the pin in Port A.
*/
void ADC_SetPin(uint8_t pin_num);
#endif // ADC_H

17
src/ADC/CMakeLists.txt Normal file
View file

@ -0,0 +1,17 @@
add_library(ADC STATIC
ADC.c
)
target_include_directories(ADC PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
if(UNIT_TESTING)
target_link_libraries(ADC
MockRegEdit
)
else()
target_link_libraries(ADC
RegEdit
)
endif()

View file

@ -56,20 +56,7 @@ target_link_options(${PROJECT_NAME} PUBLIC
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf") set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
#target_link_options(${PROJECT_NAME} PRIVATE -static -nostartfiles -T "./linker_script.ld")
# The other "targets" are size, upload, debug, production, etc #add_subdirectory(attic)
add_subdirectory(ADC)
#if(NOT TARGET size) add_subdirectory(RegEdit)
#if(NOT TARGET debug)
#if(NOT TARGET production)
#if(NOT TARGET upload)
#endif()
add_subdirectory(attic)

View file

@ -0,0 +1,7 @@
add_library(RegEdit STATIC
RegEdit.c
)
target_include_directories(RegEdit PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

62
src/RegEdit/RegEdit.c Normal file
View file

@ -0,0 +1,62 @@
/*
* Author: username
* Date: 2024
* filename: RegEdit.c
* description: module_purpose
*/
#include "RegEdit.h"
void RegEdit_SetRegister(void *reg)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr = 0xFF;
}
void RegEdit_ClearRegister(void *reg)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr = 0x00;
}
void RegEdit_SetBit(void *reg, uint8_t bit_num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr |= (uint8_t)(1 << bit_num);
}
void RegEdit_ClearBit(void *reg, uint8_t bit_num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr &= ~(1 << bit_num);
}
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
return *reg_ptr & (1 << bit_num);
}
void RegEdit_OR_Num(void *reg, uint8_t num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr |= num;
}
void RegEdit_AND_Num(void *reg, uint8_t num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr &= num;
}
void RegEdit_SetNum(void *reg, uint8_t num)
{
uint8_t *reg_ptr = (uint8_t *)reg;
*reg_ptr = num;
}
uint8_t RegEdit_ReadReg(void *reg)
{
uint8_t *reg_ptr = (uint8_t *)reg;
return *reg_ptr;
}

77
src/RegEdit/RegEdit.h Normal file
View file

@ -0,0 +1,77 @@
/**
* @brief Register Editing Interface
* @details This file is an abstraction to all the bitwise operations
* @author Jake G
* @date 2024
* @copyright None
* @file MockRegEdit.h
*/
#ifndef REGEDIT_H
#define REGEDIT_H
#include <stdbool.h>
#include <stdint.h>
/**
*
* @param reg The register address.
*/
void RegEdit_SetRegister(void *reg);
/**
*
* @param reg The register address.
*/
void RegEdit_ClearRegister(void *reg);
/**
*
* @param reg The register address.
* @param bit_num The bit location.
*/
void RegEdit_SetBit(void *reg, uint8_t bit_num);
/**
*
* @param reg The register address.
* @param bit_num The bit location.
*/
void RegEdit_ClearBit(void *reg, uint8_t bit_num);
/**
*
* @param reg The register address.
* @param bit_num The bit location.
* @return
*/
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num);
/**
*
* @param reg The register address.
* @param num The bit location.
*/
void RegEdit_OR_Num(void *reg, uint8_t num);
/**
*
* @param reg The register address.
* @param num The bit location.
*/
void RegEdit_AND_Num(void *reg, uint8_t num);
/**
*
* @param reg The register address.
* @param num The bit location.
*/
void RegEdit_SetNum(void *reg, uint8_t num);
/**
*
* @param reg The register address.
*/
uint8_t RegEdit_ReadReg(void *reg);
#endif // REGEDIT_H

384
src/ch32fun.c Executable file → Normal file
View file

@ -85,12 +85,12 @@ void __libc_init_array(void)
#define _SSP_STRING_H_ #define _SSP_STRING_H_
#define _SSP_STDIO_H_ #define _SSP_STDIO_H_
#include "ch32fun.h"
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include <limits.h>
#include <stdint.h>
#include "ch32fun.h"
#define WEAK __attribute__((weak)) #define WEAK __attribute__((weak))
@ -179,26 +179,36 @@ typedef void * mbstate_t;
WEAK size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st) WEAK size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st)
{ {
if (!s) return 1; if (!s) return 1;
if ((unsigned)wc < 0x80) { if ((unsigned)wc < 0x80)
{
*s = wc; *s = wc;
return 1; return 1;
} else if (MB_CUR_MAX == 1) { }
if (!IS_CODEUNIT(wc)) { else if (MB_CUR_MAX == 1)
{
if (!IS_CODEUNIT(wc))
{
errno = 0x02; // EILSEQ errno = 0x02; // EILSEQ
return -1; return -1;
} }
*s = wc; *s = wc;
return 1; return 1;
} else if ((unsigned)wc < 0x800) { }
else if ((unsigned)wc < 0x800)
{
*s++ = 0xc0 | (wc >> 6); *s++ = 0xc0 | (wc >> 6);
*s = 0x80 | (wc & 0x3f); *s = 0x80 | (wc & 0x3f);
return 2; return 2;
} else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) { }
else if ((unsigned)wc < 0xd800 || (unsigned)wc - 0xe000 < 0x2000)
{
*s++ = 0xe0 | (wc >> 12); *s++ = 0xe0 | (wc >> 12);
*s++ = 0x80 | ((wc >> 6) & 0x3f); *s++ = 0x80 | ((wc >> 6) & 0x3f);
*s = 0x80 | (wc & 0x3f); *s = 0x80 | (wc & 0x3f);
return 3; return 3;
} else if ((unsigned)wc-0x10000 < 0x100000) { }
else if ((unsigned)wc - 0x10000 < 0x100000)
{
*s++ = 0xf0 | (wc >> 18); *s++ = 0xf0 | (wc >> 18);
*s++ = 0x80 | ((wc >> 12) & 0x3f); *s++ = 0x80 | ((wc >> 12) & 0x3f);
*s++ = 0x80 | ((wc >> 6) & 0x3f); *s++ = 0x80 | ((wc >> 6) & 0x3f);
@ -217,40 +227,56 @@ WEAK int wctomb(char *s, wchar_t wc)
WEAK size_t strlen(const char *s) WEAK size_t strlen(const char *s)
{ {
const char *a = s; const char *a = s;
for (; *s; s++); for (; *s; s++)
;
return s - a; return s - a;
} }
WEAK size_t strnlen(const char *s, size_t n) { const char *p = memchr(s, 0, n); return p ? (size_t)(p-s) : n;} WEAK size_t strnlen(const char *s, size_t n)
WEAK void *memset(void *dest, int c, size_t n) { unsigned char *s = dest; for (; n; n--, s++) *s = c; return dest; } {
const char *p = memchr(s, 0, n);
return p ? (size_t)(p - s) : n;
}
WEAK void *memset(void *dest, int c, size_t n)
{
unsigned char *s = dest;
for (; n; n--, s++)
*s = c;
return dest;
}
WEAK char *strcpy(char *d, const char *s) WEAK char *strcpy(char *d, const char *s)
{ {
char *d0 = d; char *d0 = d;
for (; (*d=*s); s++, d++); for (; (*d = *s); s++, d++)
;
return d0; return d0;
} }
WEAK char *strncpy(char *d, const char *s, size_t n) WEAK char *strncpy(char *d, const char *s, size_t n)
{ {
char *d0 = d; char *d0 = d;
for (; n && (*d=*s); n--, s++, d++); for (; n && (*d = *s); n--, s++, d++)
;
return d0; return d0;
} }
WEAK int strcmp(const char *l, const char *r) WEAK int strcmp(const char *l, const char *r)
{ {
for (; *l==*r && *l; l++, r++); for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r; return *(unsigned char *)l - *(unsigned char *)r;
} }
WEAK int strncmp(const char *_l, const char *_r, size_t n) WEAK int strncmp(const char *_l, const char *_r, size_t n)
{ {
const unsigned char *l = (void *)_l, *r = (void *)_r; const unsigned char *l = (void *)_l, *r = (void *)_r;
if (!n--) return 0; if (!n--) return 0;
for (; *l && *r && n && *l == *r ; l++, r++, n--); for (; *l && *r && n && *l == *r; l++, r++, n--)
;
return *l - *r; return *l - *r;
} }
static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
{ {
uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1];
for (h++; *h && hw != nw; hw = hw<<8 | *++h); for (h++; *h && hw != nw; hw = hw << 8 | *++h)
;
return *h ? (char *)h - 1 : 0; return *h ? (char *)h - 1 : 0;
} }
@ -258,7 +284,8 @@ static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{ {
uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8; uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8;
uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8; uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8;
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8); for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8)
;
return *h ? (char *)h - 2 : 0; return *h ? (char *)h - 2 : 0;
} }
@ -266,7 +293,8 @@ static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{ {
uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3];
uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3];
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h); for (h += 3; *h && hw != nw; hw = hw << 8 | *++h)
;
return *h ? (char *)h - 3 : 0; return *h ? (char *)h - 3 : 0;
} }
@ -289,18 +317,29 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
if (n[l]) return 0; /* hit the end of h */ if (n[l]) return 0; /* hit the end of h */
/* Compute maximal suffix */ /* Compute maximal suffix */
ip = -1; jp = 0; k = p = 1; ip = -1;
while (jp+k<l) { jp = 0;
if (n[ip+k] == n[jp+k]) { k = p = 1;
if (k == p) { while (jp + k < l)
{
if (n[ip + k] == n[jp + k])
{
if (k == p)
{
jp += p; jp += p;
k = 1; k = 1;
} else k++; }
} else if (n[ip+k] > n[jp+k]) { else
k++;
}
else if (n[ip + k] > n[jp + k])
{
jp += k; jp += k;
k = 1; k = 1;
p = jp - ip; p = jp - ip;
} else { }
else
{
ip = jp++; ip = jp++;
k = p = 1; k = p = 1;
} }
@ -309,72 +348,100 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
p0 = p; p0 = p;
/* And with the opposite comparison */ /* And with the opposite comparison */
ip = -1; jp = 0; k = p = 1; ip = -1;
while (jp+k<l) { jp = 0;
if (n[ip+k] == n[jp+k]) { k = p = 1;
if (k == p) { while (jp + k < l)
{
if (n[ip + k] == n[jp + k])
{
if (k == p)
{
jp += p; jp += p;
k = 1; k = 1;
} else k++; }
} else if (n[ip+k] < n[jp+k]) { else
k++;
}
else if (n[ip + k] < n[jp + k])
{
jp += k; jp += k;
k = 1; k = 1;
p = jp - ip; p = jp - ip;
} else { }
else
{
ip = jp++; ip = jp++;
k = p = 1; k = p = 1;
} }
} }
if (ip+1 > ms+1) ms = ip; if (ip + 1 > ms + 1)
else p = p0; ms = ip;
else
p = p0;
/* Periodic needle? */ /* Periodic needle? */
if (memcmp(n, n+p, ms+1)) { if (memcmp(n, n + p, ms + 1))
{
mem0 = 0; mem0 = 0;
p = MAX(ms, l - ms - 1) + 1; p = MAX(ms, l - ms - 1) + 1;
} else mem0 = l-p; }
else
mem0 = l - p;
mem = 0; mem = 0;
/* Initialize incremental end-of-haystack pointer */ /* Initialize incremental end-of-haystack pointer */
z = h; z = h;
/* Search loop */ /* Search loop */
for (;;) { for (;;)
{
/* Update incremental end-of-haystack pointer */ /* Update incremental end-of-haystack pointer */
if ((size_t)(z-h) < l) { if ((size_t)(z - h) < l)
{
/* Fast estimate for MAX(l,63) */ /* Fast estimate for MAX(l,63) */
size_t grow = l | 63; size_t grow = l | 63;
const unsigned char *z2 = memchr(z, 0, grow); const unsigned char *z2 = memchr(z, 0, grow);
if (z2) { if (z2)
{
z = z2; z = z2;
if ((size_t)(z - h) < l) return 0; if ((size_t)(z - h) < l) return 0;
} else z += grow; }
else
z += grow;
} }
/* Check last byte first; advance by shift on mismatch */ /* Check last byte first; advance by shift on mismatch */
if (BITOP(byteset, h[l-1], &)) { if (BITOP(byteset, h[l - 1], &))
{
k = l - shift[h[l - 1]]; k = l - shift[h[l - 1]];
if (k) { if (k)
{
if (k < mem) k = mem; if (k < mem) k = mem;
h += k; h += k;
mem = 0; mem = 0;
continue; continue;
} }
} else { }
else
{
h += l; h += l;
mem = 0; mem = 0;
continue; continue;
} }
/* Compare right half */ /* Compare right half */
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++); for (k = MAX(ms + 1, mem); n[k] && n[k] == h[k]; k++)
if (n[k]) { ;
if (n[k])
{
h += k - ms; h += k - ms;
mem = 0; mem = 0;
continue; continue;
} }
/* Compare left half */ /* Compare left half */
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--); for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--)
;
if (k <= mem) return (char *)h; if (k <= mem) return (char *)h;
h += p; h += p;
mem = mem0; mem = mem0;
@ -385,7 +452,8 @@ WEAK char *strchr(const char *s, int c)
{ {
c = (unsigned char)c; c = (unsigned char)c;
if (!c) return (char *)s + strlen(s); if (!c) return (char *)s + strlen(s);
for (; *s && *(unsigned char *)s != c; s++); for (; *s && *(unsigned char *)s != c; s++)
;
return (char *)s; return (char *)s;
} }
@ -407,12 +475,12 @@ WEAK char *strstr(const char *h, const char *n)
return twoway_strstr((void *)h, (void *)n); return twoway_strstr((void *)h, (void *)n);
} }
WEAK void *__memrchr(const void *m, int c, size_t n) WEAK void *__memrchr(const void *m, int c, size_t n)
{ {
const unsigned char *s = m; const unsigned char *s = m;
c = (unsigned char)c; c = (unsigned char)c;
while (n--) if (s[n]==c) return (void *)(s+n); while (n--)
if (s[n] == c) return (void *)(s + n);
return 0; return 0;
} }
@ -425,18 +493,19 @@ WEAK void *memcpy(void *dest, const void *src, size_t n)
{ {
unsigned char *d = dest; unsigned char *d = dest;
const unsigned char *s = src; const unsigned char *s = src;
for (; n; n--) *d++ = *s++; for (; n; n--)
*d++ = *s++;
return dest; return dest;
} }
WEAK int memcmp(const void *vl, const void *vr, size_t n) WEAK int memcmp(const void *vl, const void *vr, size_t n)
{ {
const unsigned char *l = vl, *r = vr; const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++); for (; n && *l == *r; n--, l++, r++)
;
return n ? *l - *r : 0; return n ? *l - *r : 0;
} }
WEAK void *memmove(void *dest, const void *src, size_t n) WEAK void *memmove(void *dest, const void *src, size_t n)
{ {
char *d = dest; char *d = dest;
@ -445,10 +514,15 @@ WEAK void *memmove(void *dest, const void *src, size_t n)
if (d == s) return d; if (d == s) return d;
if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n) return memcpy(d, s, n); if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n) return memcpy(d, s, n);
if (d<s) { if (d < s)
for (; n; n--) *d++ = *s++; {
} else { for (; n; n--)
while (n) n--, d[n] = s[n]; *d++ = *s++;
}
else
{
while (n)
n--, d[n] = s[n];
} }
return dest; return dest;
@ -457,7 +531,8 @@ WEAK void *memchr(const void *src, int c, size_t n)
{ {
const unsigned char *s = src; const unsigned char *s = src;
c = (unsigned char)c; c = (unsigned char)c;
for (; n && *s != c; s++, n--); for (; n && *s != c; s++, n--)
;
return n ? (void *)s : 0; return n ? (void *)s : 0;
} }
@ -506,13 +581,15 @@ mini_itoa(long value, unsigned int radix, int uppercase, int unsig,
if (radix > 16) if (radix > 16)
return 0; return 0;
if (value < 0 && !unsig) { if (value < 0 && !unsig)
{
negative = 1; negative = 1;
value = -value; value = -value;
} }
/* This builds the string back to front ... */ /* This builds the string back to front ... */
do { do
{
int digit = value % radix; int digit = value % radix;
*(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10); *(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10);
value /= radix; value /= radix;
@ -526,7 +603,8 @@ mini_itoa(long value, unsigned int radix, int uppercase, int unsig,
/* ... now we reverse it (could do it recursively but will /* ... now we reverse it (could do it recursively but will
* conserve the stack space) */ * conserve the stack space) */
len = (pbuffer - buffer); len = (pbuffer - buffer);
for (i = 0; i < len / 2; i++) { for (i = 0; i < len / 2; i++)
{
char j = buffer[i]; char j = buffer[i];
buffer[i] = buffer[len - i - 1]; buffer[i] = buffer[len - i - 1];
buffer[len - i - 1] = j; buffer[len - i - 1] = j;
@ -542,26 +620,32 @@ mini_pad(char* ptr, int len, char pad_char, int pad_to, char *buffer)
int overflow = 0; int overflow = 0;
char *pbuffer = buffer; char *pbuffer = buffer;
if (pad_to == 0) pad_to = len; if (pad_to == 0) pad_to = len;
if(len > pad_to) { if (len > pad_to)
{
len = pad_to; len = pad_to;
overflow = 1; overflow = 1;
} }
for(i = pad_to - len; i > 0; i --) { for (i = pad_to - len; i > 0; i--)
{
*(pbuffer++) = pad_char; *(pbuffer++) = pad_char;
} }
for(i = len; i > 0; i --) { for (i = len; i > 0; i--)
{
*(pbuffer++) = *(ptr++); *(pbuffer++) = *(ptr++);
} }
len = pbuffer - buffer; len = pbuffer - buffer;
if(overflow) { if (overflow)
for (i = 0; i < 3 && pbuffer > buffer; i ++) { {
for (i = 0; i < 3 && pbuffer > buffer; i++)
{
*(pbuffer-- - 1) = '*'; *(pbuffer-- - 1) = '*';
} }
} }
return len; return len;
} }
struct mini_buff { struct mini_buff
{
char *buffer, *pbuffer; char *buffer, *pbuffer;
unsigned int buffer_len; unsigned int buffer_len;
}; };
@ -574,8 +658,10 @@ _puts(char *s, int len, void *buf)
char *p0 = b->buffer; char *p0 = b->buffer;
int i; int i;
/* Copy to buffer */ /* Copy to buffer */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++)
if(b->pbuffer == b->buffer + b->buffer_len - 1) { {
if (b->pbuffer == b->buffer + b->buffer_len - 1)
{
break; break;
} }
*(b->pbuffer++) = s[i]; *(b->pbuffer++) = s[i];
@ -600,8 +686,7 @@ void mini_printf_set_handler(
} }
#endif #endif
int int mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va)
mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va)
{ {
struct mini_buff b; struct mini_buff b;
b.buffer = buffer; b.buffer = buffer;
@ -609,14 +694,14 @@ mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list v
b.buffer_len = buffer_len; b.buffer_len = buffer_len;
if (buffer_len == 0) buffer = (void *)0; if (buffer_len == 0) buffer = (void *)0;
int n = mini_vpprintf(_puts, (buffer != (void *)0) ? &b : (void *)0, fmt, va); int n = mini_vpprintf(_puts, (buffer != (void *)0) ? &b : (void *)0, fmt, va);
if(buffer == (void*) 0) { if (buffer == (void *)0)
{
return n; return n;
} }
return b.pbuffer - b.buffer; return b.pbuffer - b.buffer;
} }
int int mini_vpprintf(int (*puts)(char *s, int len, void *buf), void *buf, const char *fmt, va_list va)
mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va)
{ {
char bf[24]; char bf[24];
char bf2[24]; char bf2[24];
@ -624,17 +709,23 @@ mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *f
#ifdef MINI_PRINTF_ENABLE_OBJECTS #ifdef MINI_PRINTF_ENABLE_OBJECTS
void *obj; void *obj;
#endif #endif
if(puts == (void*)0) { if (puts == (void *)0)
{
/* run puts in counting mode. */ /* run puts in counting mode. */
puts = _puts; buf = (void*)0; puts = _puts;
buf = (void *)0;
} }
int n = 0; int n = 0;
while ((ch=*(fmt++))) { while ((ch = *(fmt++)))
{
int len; int len;
if (ch!='%') { if (ch != '%')
{
len = 1; len = 1;
len = puts(&ch, len, buf); len = puts(&ch, len, buf);
} else { }
else
{
char pad_char = ' '; char pad_char = ' ';
int pad_to = 0; int pad_to = 0;
char l = 0; char l = 0;
@ -644,29 +735,39 @@ mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *f
/* Zero padding requested */ /* Zero padding requested */
if (ch == '0') pad_char = '0'; if (ch == '0') pad_char = '0';
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9')
{
pad_to = pad_to * 10 + (ch - '0'); pad_to = pad_to * 10 + (ch - '0');
ch = *(fmt++); ch = *(fmt++);
} }
if(pad_to > (signed int) sizeof(bf)) { if (pad_to > (signed int)sizeof(bf))
{
pad_to = sizeof(bf); pad_to = sizeof(bf);
} }
if (ch == 'l') { if (ch == 'l')
{
l = 1; l = 1;
ch = *(fmt++); ch = *(fmt++);
} }
switch (ch) { switch (ch)
{
case 0: case 0:
goto end; goto end;
case 'u': case 'u':
case 'd': case 'd':
if(l) { if (l)
{
len = mini_itoa(va_arg(va, unsigned long), 10, 0, (ch == 'u'), bf2); len = mini_itoa(va_arg(va, unsigned long), 10, 0, (ch == 'u'), bf2);
} else { }
if(ch == 'u') { else
{
if (ch == 'u')
{
len = mini_itoa((unsigned long)va_arg(va, unsigned int), 10, 0, 1, bf2); len = mini_itoa((unsigned long)va_arg(va, unsigned int), 10, 0, 1, bf2);
} else { }
else
{
len = mini_itoa((long)va_arg(va, int), 10, 0, 0, bf2); len = mini_itoa((long)va_arg(va, int), 10, 0, 0, bf2);
} }
} }
@ -676,9 +777,12 @@ mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *f
case 'x': case 'x':
case 'X': case 'X':
if(l) { if (l)
{
len = mini_itoa(va_arg(va, unsigned long), 16, (ch == 'X'), 1, bf2); len = mini_itoa(va_arg(va, unsigned long), 16, (ch == 'X'), 1, bf2);
} else { }
else
{
len = mini_itoa((unsigned long)va_arg(va, unsigned int), 16, (ch == 'X'), 1, bf2); len = mini_itoa((unsigned long)va_arg(va, unsigned int), 16, (ch == 'X'), 1, bf2);
} }
len = mini_pad(bf2, len, pad_char, pad_to, bf); len = mini_pad(bf2, len, pad_char, pad_to, bf);
@ -694,10 +798,13 @@ mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *f
case 's': case 's':
ptr = va_arg(va, char *); ptr = va_arg(va, char *);
len = mini_strlen(ptr); len = mini_strlen(ptr);
if (pad_to > 0) { if (pad_to > 0)
{
len = mini_pad(ptr, len, pad_char, pad_to, bf); len = mini_pad(ptr, len, pad_char, pad_to, bf);
len = puts(bf, len, buf); len = puts(bf, len, buf);
} else { }
else
{
len = puts(ptr, len, buf); len = puts(ptr, len, buf);
} }
break; break;
@ -706,10 +813,13 @@ mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *f
case 'R': /* Object by representation (e.g. repr)*/ case 'R': /* Object by representation (e.g. repr)*/
obj = va_arg(va, void *); obj = va_arg(va, void *);
len = mini_handler(mini_handler_data, obj, ch, pad_to, &ptr); len = mini_handler(mini_handler_data, obj, ch, pad_to, &ptr);
if (pad_to > 0) { if (pad_to > 0)
{
len = mini_pad(ptr, len, pad_char, pad_to, bf); len = mini_pad(ptr, len, pad_char, pad_to, bf);
len = puts(bf, len, buf); len = puts(bf, len, buf);
} else { }
else
{
len = puts(ptr, len, buf); len = puts(ptr, len, buf);
} }
mini_handler_freeor(mini_handler_data, ptr); mini_handler_freeor(mini_handler_data, ptr);
@ -727,9 +837,7 @@ end:
return n; return n;
} }
int mini_snprintf(char *buffer, unsigned int buffer_len, const char *fmt, ...)
int
mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...)
{ {
int ret; int ret;
va_list va; va_list va;
@ -740,8 +848,7 @@ mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...)
return ret; return ret;
} }
int int mini_pprintf(int (*puts)(char *s, int len, void *buf), void *buf, const char *fmt, ...)
mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...)
{ {
int ret; int ret;
va_list va; va_list va;
@ -752,7 +859,6 @@ mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt
return ret; return ret;
} }
/* /*
C version of CH32V003 Startup .s file from WCH C version of CH32V003 Startup .s file from WCH
This file is public domain where possible or the following where not: This file is public domain where possible or the following where not:
@ -777,13 +883,15 @@ extern uint32_t * _edata;
#if FUNCONF_USE_DEBUGPRINTF #if FUNCONF_USE_DEBUGPRINTF
static void PrintN(uint32_t n) static void PrintN(uint32_t n)
{ {
while( (*DMDATA0) & 0x80 ); while ((*DMDATA0) & 0x80)
;
// Write out character. // Write out character.
*DMDATA0 = 0x78302088; //" 0x" *DMDATA0 = 0x78302088; //" 0x"
int shift; int shift;
for (shift = 28; shift >= 0; shift -= 4) for (shift = 28; shift >= 0; shift -= 4)
{ {
while( (*DMDATA0) & 0x80 ); while ((*DMDATA0) & 0x80)
;
int s = (n >> shift) & 0xf; int s = (n >> shift) & 0xf;
s += (s < 10) ? '0' : ('a' - 10); s += (s < 10) ? '0' : ('a' - 10);
*DMDATA0 = 0x85 | (s << 8); //" 0x" *DMDATA0 = 0x85 | (s << 8); //" 0x"
@ -817,9 +925,11 @@ void DefaultIRQHandler( void )
PrintN(__get_MTVAL()); PrintN(__get_MTVAL());
PrintN(__get_MCAUSE()); PrintN(__get_MCAUSE());
#if FUNCONF_USE_DEBUGPRINTF #if FUNCONF_USE_DEBUGPRINTF
while( (*DMDATA0) & 0x80 ); while ((*DMDATA0) & 0x80)
;
*DMDATA0 = 0x0a85; *DMDATA0 = 0x0a85;
while( (*DMDATA0) & 0x80 ); while ((*DMDATA0) & 0x80)
;
*DMDATA0 = 0xaaaaaa83; *DMDATA0 = 0xaaaaaa83;
#elif FUNCONF_USE_UARTPRINTF #elif FUNCONF_USE_UARTPRINTF
putchar('\n'); putchar('\n');
@ -967,7 +1077,6 @@ void TIM2_CC_IRQHandler( void ) __attribute__((section(".text.vector_handler")
void TIM2_TRG_IRQHandler(void) __attribute__((section(".text.vector_handler"))) __attribute((weak, alias("DefaultIRQHandler"))) __attribute__((used)); void TIM2_TRG_IRQHandler(void) __attribute__((section(".text.vector_handler"))) __attribute((weak, alias("DefaultIRQHandler"))) __attribute__((used));
void TIM2_BRK_IRQHandler(void) __attribute__((section(".text.vector_handler"))) __attribute((weak, alias("DefaultIRQHandler"))) __attribute__((used)); void TIM2_BRK_IRQHandler(void) __attribute__((section(".text.vector_handler"))) __attribute((weak, alias("DefaultIRQHandler"))) __attribute__((used));
void InterruptVector() __attribute__((naked)) __attribute((section(".init"))) __attribute((weak, alias("InterruptVectorDefault"))) __attribute((naked)); void InterruptVector() __attribute__((naked)) __attribute((section(".init"))) __attribute((weak, alias("InterruptVectorDefault"))) __attribute((naked));
void InterruptVectorDefault() __attribute__((naked)) __attribute((section(".init"))) __attribute((naked)); void InterruptVectorDefault() __attribute__((naked)) __attribute((section(".init"))) __attribute((naked));
void handle_reset(void) __attribute__((section(".text.handle_reset"))); void handle_reset(void) __attribute__((section(".text.handle_reset")));
@ -1103,8 +1212,7 @@ void handle_reset( void )
#else #else
: : : :
#endif #endif
: "a0", "a1", "a2", "a3", "memory" : "a0", "a1", "a2", "a3", "memory");
);
// Setup the interrupt vector, processor status and INTSYSCR. // Setup the interrupt vector, processor status and INTSYSCR.
asm volatile( asm volatile(
@ -1126,8 +1234,7 @@ void handle_reset( void )
" la t0, InterruptVector\n\ " la t0, InterruptVector\n\
ori t0, t0, 3\n\ ori t0, t0, 3\n\
csrw mtvec, t0\n" csrw mtvec, t0\n"
: : [InterruptVector]"r"(InterruptVector) : "t0", "memory" : : [InterruptVector] "r"(InterruptVector) : "t0", "memory");
);
#if defined(FUNCONF_SYSTICK_USE_HCLK) && FUNCONF_SYSTICK_USE_HCLK && !defined(CH32V10x) #if defined(FUNCONF_SYSTICK_USE_HCLK) && FUNCONF_SYSTICK_USE_HCLK && !defined(CH32V10x)
SysTick->CTLR = 5; SysTick->CTLR = 5;
@ -1194,8 +1301,7 @@ __attribute__ ((naked)) int setjmp( jmp_buf env )
#endif #endif
" li a0, 0\n" " li a0, 0\n"
" ret\n" " ret\n");
);
} }
__attribute__((naked)) void longjmp(jmp_buf env, int val) __attribute__((naked)) void longjmp(jmp_buf env, int val)
@ -1237,8 +1343,7 @@ __attribute__ ((naked)) void longjmp( jmp_buf env, int val )
" seqz a0, a1\n" // a0 = (a1 == 0) ? 1 : 0 " seqz a0, a1\n" // a0 = (a1 == 0) ? 1 : 0
" add a0, a0, a1\n" " add a0, a0, a1\n"
" ret\n" " ret\n");
);
__builtin_unreachable(); // Disable warning about no return. __builtin_unreachable(); // Disable warning about no return.
} }
@ -1278,8 +1383,10 @@ void SetupUART( int uartBRR )
// For debug writing to the UART. // For debug writing to the UART.
WEAK int _write(int fd, const char *buf, int size) WEAK int _write(int fd, const char *buf, int size)
{ {
for(int i = 0; i < size; i++){ for (int i = 0; i < size; i++)
while( !(USART1->STATR & USART_FLAG_TC)); {
while (!(USART1->STATR & USART_FLAG_TC))
;
USART1->DATAR = *buf++; USART1->DATAR = *buf++;
} }
return size; return size;
@ -1288,7 +1395,8 @@ WEAK int _write(int fd, const char *buf, int size)
// single char to UART // single char to UART
WEAK int putchar(int c) WEAK int putchar(int c)
{ {
while( !(USART1->STATR & USART_FLAG_TC)); while (!(USART1->STATR & USART_FLAG_TC))
;
USART1->DATAR = (const char)c; USART1->DATAR = (const char)c;
return 1; return 1;
} }
@ -1296,9 +1404,12 @@ WEAK int putchar(int c)
#if defined(FUNCONF_USE_DEBUGPRINTF) && FUNCONF_USE_DEBUGPRINTF #if defined(FUNCONF_USE_DEBUGPRINTF) && FUNCONF_USE_DEBUGPRINTF
void handle_debug_input(int numbytes, uint8_t *data) __attribute__((weak)); void handle_debug_input(int numbytes, uint8_t *data) __attribute__((weak));
void handle_debug_input( int numbytes, uint8_t * data ) { (void)numbytes; (void)data; } void handle_debug_input(int numbytes, uint8_t *data)
{
(void)numbytes;
(void)data;
}
static void internal_handle_input(volatile uint32_t *dmdata0) static void internal_handle_input(volatile uint32_t *dmdata0)
{ {
@ -1310,7 +1421,6 @@ static void internal_handle_input( volatile uint32_t * dmdata0 )
} }
} }
void poll_input(void) void poll_input(void)
{ {
volatile uint32_t *dmdata0 = (volatile uint32_t *)DMDATA0; volatile uint32_t *dmdata0 = (volatile uint32_t *)DMDATA0;
@ -1321,7 +1431,6 @@ void poll_input( void )
} }
} }
// MSB .... LSB // MSB .... LSB
// DMDATA0: char3 char2 char1 [status word] // DMDATA0: char3 char2 char1 [status word]
// where [status word] is: // where [status word] is:
@ -1422,7 +1531,6 @@ void SetupDebugPrintf( void )
int WaitForDebuggerToAttach(int timeout_ms) int WaitForDebuggerToAttach(int timeout_ms)
{ {
#if defined(CH32V20x) || defined(CH32V30x) #if defined(CH32V20x) || defined(CH32V30x)
#define systickcnt_t uint64_t #define systickcnt_t uint64_t
#define SYSTICKCNT SysTick->CNT #define SYSTICKCNT SysTick->CNT
@ -1439,7 +1547,8 @@ int WaitForDebuggerToAttach( int timeout_ms )
const systickcnt_t timeout = timeout_ms * ticks_per_ms; const systickcnt_t timeout = timeout_ms * ticks_per_ms;
// Wait for the sentinel to become zero. // Wait for the sentinel to become zero.
while( !DidDebuggerAttach() ) { while (!DidDebuggerAttach())
{
if (timeout_ms && (SYSTICKCNT - start) > timeout) return 1; if (timeout_ms && (SYSTICKCNT - start) > timeout) return 1;
} }
@ -1471,13 +1580,16 @@ void DelaySysTick( uint32_t n )
{ {
#ifdef CH32V003 #ifdef CH32V003
uint32_t targend = SysTick->CNT + n; uint32_t targend = SysTick->CNT + n;
while( ((int32_t)( SysTick->CNT - targend )) < 0 ); while (((int32_t)(SysTick->CNT - targend)) < 0)
;
#elif defined(CH32V20x) || defined(CH32V30x) #elif defined(CH32V20x) || defined(CH32V30x)
uint64_t targend = SysTick->CNT + n; uint64_t targend = SysTick->CNT + n;
while( ((int64_t)( SysTick->CNT - targend )) < 0 ); while (((int64_t)(SysTick->CNT - targend)) < 0)
;
#elif defined(CH32V10x) || defined(CH32X03x) #elif defined(CH32V10x) || defined(CH32X03x)
uint32_t targend = SysTick->CNTL + n; uint32_t targend = SysTick->CNTL + n;
while( ((int32_t)( SysTick->CNTL - targend )) < 0 ); while (((int32_t)(SysTick->CNTL - targend)) < 0)
;
#else #else
#error DelaySysTick not defined. #error DelaySysTick not defined.
#endif #endif
@ -1603,10 +1715,12 @@ void SystemInit( void )
RCC->INTR = 0x009F0000; // Clear PLL, CSSC, HSE, HSI and LSI ready flags. RCC->INTR = 0x009F0000; // Clear PLL, CSSC, HSE, HSI and LSI ready flags.
#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL #if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
while((RCC->CTLR & RCC_PLLRDY) == 0); // Wait till PLL is ready while ((RCC->CTLR & RCC_PLLRDY) == 0)
; // Wait till PLL is ready
uint32_t tmp32 = RCC->CFGR0 & ~(0x03); // clr the SW uint32_t tmp32 = RCC->CFGR0 & ~(0x03); // clr the SW
RCC->CFGR0 = tmp32 | RCC_SW_PLL; // Select PLL as system clock source RCC->CFGR0 = tmp32 | RCC_SW_PLL; // Select PLL as system clock source
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08); // Wait till PLL is used as system clock source while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
; // Wait till PLL is used as system clock source
#endif #endif
#if defined(FUNCONF_USE_UARTPRINTF) && FUNCONF_USE_UARTPRINTF #if defined(FUNCONF_USE_UARTPRINTF) && FUNCONF_USE_UARTPRINTF
@ -1634,12 +1748,13 @@ void funAnalogInit( void )
// Reset calibration // Reset calibration
ADC1->CTLR2 |= ADC_RSTCAL; ADC1->CTLR2 |= ADC_RSTCAL;
while(ADC1->CTLR2 & ADC_RSTCAL); while (ADC1->CTLR2 & ADC_RSTCAL)
;
// Calibrate // Calibrate
ADC1->CTLR2 |= ADC_CAL; ADC1->CTLR2 |= ADC_CAL;
while(ADC1->CTLR2 & ADC_CAL); while (ADC1->CTLR2 & ADC_CAL)
;
} }
int funAnalogRead(int nAnalogNumber) int funAnalogRead(int nAnalogNumber)
@ -1650,7 +1765,8 @@ int funAnalogRead( int nAnalogNumber )
ADC1->CTLR2 |= ADC_SWSTART; ADC1->CTLR2 |= ADC_SWSTART;
// wait for conversion complete // wait for conversion complete
while(!(ADC1->STATR & ADC_EOC)); while (!(ADC1->STATR & ADC_EOC))
;
// get result // get result
return ADC1->RDATAR; return ADC1->RDATAR;
@ -1660,7 +1776,11 @@ int funAnalogRead( int nAnalogNumber )
#ifdef CPLUSPLUS #ifdef CPLUSPLUS
// This is required to allow pure virtual functions to be defined. // This is required to allow pure virtual functions to be defined.
extern void __cxa_pure_virtual() { while (1); } extern void __cxa_pure_virtual()
{
while (1)
;
}
// These magic symbols are provided by the linker. // These magic symbols are provided by the linker.
extern void (*__preinit_array_start[])(void) __attribute__((weak)); extern void (*__preinit_array_start[])(void) __attribute__((weak));

155
src/ch32fun.h Executable file → Normal file
View file

@ -59,8 +59,6 @@
by setting FUNCONF_DEBUG_HARDFAULT to 0. by setting FUNCONF_DEBUG_HARDFAULT to 0.
*/ */
/****************************************************************************** /******************************************************************************
* CH32V003 Fun Configs; please define any non-default options in funconfig.h * * CH32V003 Fun Configs; please define any non-default options in funconfig.h *
@ -142,7 +140,6 @@
#define INTERRUPT_DECORATOR __attribute__((interrupt)) #define INTERRUPT_DECORATOR __attribute__((interrupt))
#endif #endif
#if !defined(FUNCONF_USE_CLK_SEC) #if !defined(FUNCONF_USE_CLK_SEC)
#define FUNCONF_USE_CLK_SEC 1 // use clock security system by default #define FUNCONF_USE_CLK_SEC 1 // use clock security system by default
#endif #endif
@ -278,9 +275,9 @@
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
@ -327,11 +324,23 @@ typedef uint64_t u64;
typedef __IO int64_t vs64; typedef __IO int64_t vs64;
typedef int64_t s64; typedef int64_t s64;
typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus; typedef enum
{
NoREADY = 0,
READY = !NoREADY
} ErrorStatus;
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; typedef enum
{
DISABLE = 0,
ENABLE = !DISABLE
} FunctionalState;
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; typedef enum
{
RESET = 0,
SET = !RESET
} FlagStatus, ITStatus;
#define RV_STATIC_INLINE static inline #define RV_STATIC_INLINE static inline
#endif // __ASSEMBLER__ #endif // __ASSEMBLER__
@ -363,28 +372,37 @@ typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
// Enable Global Interrupt // Enable Global Interrupt
RV_STATIC_INLINE void __enable_irq() RV_STATIC_INLINE void __enable_irq()
{ {
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) ); uint32_t result;
result |= 0x88; __ASM volatile( ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mstatus" : "=r"(result));
result |= 0x88;
__ASM volatile(ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r"(result));
} }
// Disable Global Interrupt // Disable Global Interrupt
RV_STATIC_INLINE void __disable_irq() RV_STATIC_INLINE void __disable_irq()
{ {
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) ); uint32_t result;
result &= ~0x88; __ASM volatile( ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mstatus" : "=r"(result));
result &= ~0x88;
__ASM volatile(ADD_ARCH_ZICSR "csrw mstatus, %0" : : "r"(result));
} }
// Is Global Interrupt enabled (1 = yes, 0 = no) // Is Global Interrupt enabled (1 = yes, 0 = no)
RV_STATIC_INLINE uint8_t __isenabled_irq(void) RV_STATIC_INLINE uint8_t __isenabled_irq(void)
{ {
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mstatus": "=r"(result) ); uint32_t result;
__ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mstatus" : "=r"(result));
return (result & 0x08) != 0u; return (result & 0x08) != 0u;
} }
// Get stack pointer (returns the stack pointer) // Get stack pointer (returns the stack pointer)
RV_STATIC_INLINE uint32_t __get_cpu_sp(void) RV_STATIC_INLINE uint32_t __get_cpu_sp(void)
{ {
uint32_t result; __ASM volatile( ADD_ARCH_ZICSR "mv %0, sp" : "=r"(result)); uint32_t result;
__ASM volatile(ADD_ARCH_ZICSR "mv %0, sp" : "=r"(result));
return result; return result;
} }
@ -466,11 +484,13 @@ RV_STATIC_INLINE uint32_t NVIC_get_enabled_IRQs()
RV_STATIC_INLINE void NVIC_clear_all_IRQs_except(uint8_t IRQn_to_keep) RV_STATIC_INLINE void NVIC_clear_all_IRQs_except(uint8_t IRQn_to_keep)
{ {
if (!(IRQn_to_keep >> 5)) { // IRQn_to_keep < 32 if (!(IRQn_to_keep >> 5))
{ // IRQn_to_keep < 32
NVIC->IRER[0] = (~0) & (~(1 << IRQn_to_keep)); NVIC->IRER[0] = (~0) & (~(1 << IRQn_to_keep));
NVIC->IRER[1] = (~0); NVIC->IRER[1] = (~0);
} }
else { else
{
IRQn_to_keep = IRQn_to_keep >> 5; IRQn_to_keep = IRQn_to_keep >> 5;
NVIC->IRER[0] = (~0); NVIC->IRER[0] = (~0);
NVIC->IRER[1] = (~0) & (~(1 << IRQn_to_keep)); NVIC->IRER[1] = (~0) & (~(1 << IRQn_to_keep));
@ -512,7 +532,8 @@ __attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void)
* *
* @return none * @return none
*/ */
RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState)
{
if (num > 1) return; if (num > 1) return;
if (NewState != DISABLE) if (NewState != DISABLE)
@ -520,7 +541,8 @@ RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, Func
NVIC->VTFIDR[num] = IRQn; NVIC->VTFIDR[num] = IRQn;
NVIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) | 0x1); NVIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) | 0x1);
} }
else{ else
{
NVIC->VTFIDR[num] = IRQn; NVIC->VTFIDR[num] = IRQn;
NVIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) & (~0x1)); NVIC->VTFADDR[num] = ((addr & 0xFFFFFFFE) & (~0x1));
} }
@ -552,7 +574,8 @@ static inline void __set_INTSYSCR( uint32_t value )
static inline uint32_t __get_FFLAGS(void) static inline uint32_t __get_FFLAGS(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "fflags" : "=r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"fflags" : "=r"(result));
return (result); return (result);
} }
@ -566,7 +589,8 @@ static inline void __set_FFLAGS(uint32_t value)
static inline uint32_t __get_FRM(void) static inline uint32_t __get_FRM(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "frm" : "=r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"frm" : "=r"(result));
return (result); return (result);
} }
@ -580,7 +604,8 @@ static inline void __set_FRM(uint32_t value)
static inline uint32_t __get_FCSR(void) static inline uint32_t __get_FCSR(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "fcsr" : "=r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"fcsr" : "=r"(result));
return (result); return (result);
} }
@ -624,7 +649,8 @@ static inline void __set_MISA(uint32_t value)
static inline uint32_t __get_MTVEC(void) static inline uint32_t __get_MTVEC(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mtvec": "=r"(result)); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mtvec" : "=r"(result));
return (result); return (result);
} }
@ -638,7 +664,8 @@ static inline void __set_MTVEC(uint32_t value)
static inline uint32_t __get_MSCRATCH(void) static inline uint32_t __get_MSCRATCH(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mscratch" : "=r"(result)); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mscratch" : "=r"(result));
return (result); return (result);
} }
@ -652,7 +679,8 @@ static inline void __set_MSCRATCH(uint32_t value)
static inline uint32_t __get_MEPC(void) static inline uint32_t __get_MEPC(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mepc" : "=r"(result)); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mepc" : "=r"(result));
return (result); return (result);
} }
@ -666,7 +694,8 @@ static inline void __set_MEPC(uint32_t value)
static inline uint32_t __get_MCAUSE(void) static inline uint32_t __get_MCAUSE(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mcause": "=r"(result)); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mcause" : "=r"(result));
return (result); return (result);
} }
@ -680,7 +709,8 @@ static inline void __set_MCAUSE(uint32_t value)
static inline uint32_t __get_MTVAL(void) static inline uint32_t __get_MTVAL(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( ADD_ARCH_ZICSR "csrr %0," "mtval" : "=r" (result) ); __ASM volatile(ADD_ARCH_ZICSR "csrr %0,"
"mtval" : "=r"(result));
return (result); return (result);
} }
@ -732,7 +762,6 @@ static inline uint32_t __get_DEBUG_CR(void)
return (result); return (result);
} }
// Set the DBGMCU_CR Register value // Set the DBGMCU_CR Register value
static inline void __set_DEBUG_CR(uint32_t value) static inline void __set_DEBUG_CR(uint32_t value)
{ {
@ -743,7 +772,8 @@ static inline void __set_DEBUG_CR(uint32_t value)
static inline uint32_t __get_SP(void) static inline uint32_t __get_SP(void)
{ {
uint32_t result; uint32_t result;
__ASM volatile( "mv %0,""sp": "=r"(result):); __ASM volatile("mv %0,"
"sp" : "=r"(result) :);
return (result); return (result);
} }
#endif // CH32V003 #endif // CH32V003
@ -784,13 +814,13 @@ void longjmp( jmp_buf env, int val );
#endif /* __CORE_RISCV_H__ */ #endif /* __CORE_RISCV_H__ */
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/* SYSTICK info /* SYSTICK info
@ -828,26 +858,58 @@ extern "C" {
// For pins, use things like PA8, PB15 // For pins, use things like PA8, PB15
// For configuration, use things like GPIO_CFGLR_OUT_10Mhz_PP // For configuration, use things like GPIO_CFGLR_OUT_10Mhz_PP
#define funDigitalWrite( pin, value ) { GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)); } #define funDigitalWrite(pin, value) \
{ \
GpioOf(pin)->BSHR = 1 << ((!(value)) * 16 + ((pin) & 0xf)); \
}
#if defined(CH32X03x) #if defined(CH32X03x)
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC ); } #define funGpioInitAll() \
#define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); } { \
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC); \
}
#define funPinMode(pin, mode) \
{ \
*((&GpioOf(pin)->CFGLR) + ((pin & 0x8) >> 3)) = ((*((&GpioOf(pin)->CFGLR) + ((pin & 0x8) >> 3))) & (~(0xf << (4 * ((pin) & 0x7))))) | ((mode) << (4 * ((pin) & 0x7))); \
}
#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x)
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ); } #define funGpioInitAll() \
#define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); } { \
#define funGpioInitB() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB ); } RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD); \
}
#define funPinMode(pin, mode) \
{ \
*((&GpioOf(pin)->CFGLR) + ((pin & 0x8) >> 3)) = ((*((&GpioOf(pin)->CFGLR) + ((pin & 0x8) >> 3))) & (~(0xf << (4 * ((pin) & 0x7))))) | ((mode) << (4 * ((pin) & 0x7))); \
}
#define funGpioInitB() \
{ \
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB); \
}
#else #else
#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ); } #define funGpioInitAll() \
#define funPinMode( pin, mode ) { GpioOf(pin)->CFGLR = (GpioOf(pin)->CFGLR & (~(0xf<<(4*((pin)&0xf))))) | ((mode)<<(4*((pin)&0xf))); } { \
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD); \
}
#define funPinMode(pin, mode) \
{ \
GpioOf(pin)->CFGLR = (GpioOf(pin)->CFGLR & (~(0xf << (4 * ((pin) & 0xf))))) | ((mode) << (4 * ((pin) & 0xf))); \
}
#endif #endif
#define funGpioInitA() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA ); } #define funGpioInitA() \
#define funGpioInitC() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC ); } { \
#define funGpioInitD() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD ); } RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA); \
}
#define funGpioInitC() \
{ \
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC); \
}
#define funGpioInitD() \
{ \
RCC->APB2PCENR |= (RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD); \
}
#define funDigitalRead(pin) ((int)((GpioOf(pin)->INDR >> ((pin) & 0xf)) & 1)) #define funDigitalRead(pin) ((int)((GpioOf(pin)->INDR >> ((pin) & 0xf)) & 1))
#define ANALOG_0 0 #define ANALOG_0 0
#define ANALOG_1 1 #define ANALOG_1 1
#define ANALOG_2 2 #define ANALOG_2 2
@ -865,7 +927,6 @@ extern "C" {
#if defined(__riscv) || defined(__riscv__) || defined(CH32V003FUN_BASE) #if defined(__riscv) || defined(__riscv__) || defined(CH32V003FUN_BASE)
// Stuff that can only be compiled on device (not for the programmer, or other host programs) // Stuff that can only be compiled on device (not for the programmer, or other host programs)
// Initialize the ADC calibrate it and set some sane defaults. // Initialize the ADC calibrate it and set some sane defaults.
@ -884,13 +945,13 @@ void DefaultIRQHandler( void ) __attribute__((section(".text.vector_handler")))
void DelaySysTick(uint32_t n); void DelaySysTick(uint32_t n);
// Depending on a LOT of factors, it's about 6 cycles per n. // Depending on a LOT of factors, it's about 6 cycles per n.
// **DO NOT send it zero or less.** // **DO NOT send it zero or less.**
#ifndef __MACOSX__ #ifndef __MACOSX__
#ifndef __DELAY_TINY_DEFINED__ #ifndef __DELAY_TINY_DEFINED__
#define __DELAY_TINY_DEFINED__ #define __DELAY_TINY_DEFINED__
static inline void Delay_Tiny( int n ) { static inline void Delay_Tiny(int n)
{
__ASM volatile("\ __ASM volatile("\
mv a5, %[n]\n\ mv a5, %[n]\n\
1: \ 1: \
@ -938,7 +999,6 @@ void poll_input( void );
// Receiving bytes from host. Override if you wish. // Receiving bytes from host. Override if you wish.
void handle_debug_input(int numbytes, uint8_t *data); void handle_debug_input(int numbytes, uint8_t *data);
// Functions from ch32fun.c // Functions from ch32fun.c
#include <stdarg.h> #include <stdarg.h>
@ -949,7 +1009,6 @@ int mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char
#endif // __ASSEMBLER__ #endif // __ASSEMBLER__
/* /*
* This file contains various parts of the official WCH EVT Headers which * This file contains various parts of the official WCH EVT Headers which
* were originally under a restrictive license. * were originally under a restrictive license.
@ -990,6 +1049,4 @@ int mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char
}; };
#endif #endif
#endif // __CH32FUN_H #endif // __CH32FUN_H

View file

@ -4,4 +4,3 @@
#define CH32V003 1 #define CH32V003 1
#endif #endif

17
tests/ADC/CMakeLists.txt Normal file
View file

@ -0,0 +1,17 @@
# TEST_RUNNER
add_library(test_ADC
test_ADC.cpp
)
target_link_libraries(test_ADC
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
ADC
MockRegEdit
)
#Needed for the tests to function
include_directories(
/usr/local/avr/include/avr
#/usr/lib/avr/include/avr
)

192
tests/ADC/test_ADC.cpp Normal file
View file

@ -0,0 +1,192 @@
/*
* Author: Jake G
* Date: 2024
* filename: test_ADC.c
* description: module_purpose
*/
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTestExt/MockSupport.h"
#include <cstdint>
//This define allows us to dircetly include the device header without error.
#define _AVR_IO_H_
extern "C"
{
#include <iotn404.h> //ATtiny404 header fille.
#include "ADC.h"
}
TEST_GROUP(test_ADC)
{
void setup()
{
}
void teardown()
{
mock().checkExpectations();
mock().clear();
}
};
TEST(test_ADC, FirstTest)
{
CHECK(true);
}
TEST(test_ADC, ADC_SetupSetsRegisters)
{
//Clears control register A for ADC0
mock().expectOneCall("RegEdit_SetNum")
.withPointerParameter("reg", (void *) &ADC0.CTRLA)
.withUnsignedIntParameter("num", 0x00);
//Sets The sample accumulation number to 32.
mock().expectOneCall("RegEdit_SetNum")
.withPointerParameter("reg", (void *) &ADC0.CTRLB)
.withUnsignedIntParameter("num", 0x5);
//Sets the voltage reference to VDD or VCC.
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &ADC0.CTRLC)
.withUnsignedIntParameter("bit_num", 4);
//Sets the pre-scalar for the adc sample rate.
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &ADC0.CTRLC)
.withUnsignedIntParameter("bit_num", 2);
//Setup an Initalization delay.
mock().expectOneCall("RegEdit_OR_Num")
.withPointerParameter("reg", (void *) &ADC0.CTRLD)
.withUnsignedIntParameter("num", (2<<5));
//Set the bit for ADC variation during readings.
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &ADC0.CTRLD)
.withUnsignedIntParameter("bit_num", 4);
ADC_Setup();
}
TEST(test_ADC, ADC_InitPortAPin7UsesCorrectRegisters)
{
//Check for setting the direction to input.
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", (void *) &PORTA.DIR)
.withUnsignedIntParameter("bit_num", 7);
//Check that the pullup is off
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", (void *) &PORTA.OUT)
.withUnsignedIntParameter("bit_num", 7);
//Set the ISC(input sense config) to disable digital input
//buffering and reduce the noise on ADC usage.
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &PORTA.PIN7CTRL)
.withUnsignedIntParameter("bit_num", PORT_ISC_INPUT_DISABLE_gc);
ADC_Init(7);
}
TEST(test_ADC, ADC_InitPortAPin0UsesCorrectRegisters)
{
//Check for setting the direction to input.
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", (void *) &PORTA.DIR)
.withUnsignedIntParameter("bit_num", 0);
//Check that the pullup is off
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", (void *) &PORTA.OUT)
.withUnsignedIntParameter("bit_num", 0);
//Set the ISC(input sense config) to disable digital input
//buffering and reduce the noise on ADC usage.
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &PORTA.PIN0CTRL)
.withUnsignedIntParameter("bit_num", PORT_ISC_INPUT_DISABLE_gc);
ADC_Init(0);
}
TEST(test_ADC, ADC_InitDoesNothingOnHighPinNumbers)
{
mock().expectNoCall("RegEdit_SetBit");
ADC_Init(8);
}
TEST(test_ADC, ADC_EnablePasses)
{
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", (void *) &ADC0.CTRLA)
.withUnsignedIntParameter("bit_num", 0);
ADC_Enable();
}
TEST(test_ADC, ADC_DisablePasses)
{
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", (void *) &ADC0.CTRLA)
.withUnsignedIntParameter("bit_num", 0);
ADC_Disable();
}
TEST(test_ADC, ADC_SetPinSetsRightRegisters)
{
//It clears existing MUXPOS register values.
mock().expectOneCall("RegEdit_ClearRegister")
.withPointerParameter("reg", (void *) &ADC0.MUXPOS);
//It Correctly sets the pin number.
mock().expectOneCall("RegEdit_SetNum")
.withPointerParameter("reg", (void *) &ADC0.MUXPOS)
.withUnsignedIntParameter("num", 4);
ADC_SetPin(4);
}
TEST(test_ADC, ADC_SetPinFailsOnInvalidPin)
{
ADC_SetPin(8);
}
static uint16_t ADC_ReadValueFake(uint8_t pin_num)
{
return 512;
}
TEST_GROUP(test_ADCRead)
{
void setup()
{
UT_PTR_SET(ADC_ReadValue, ADC_ReadValueFake);
}
void teardown()
{
}
};
TEST(test_ADCRead, FunctionPointerSwapWorks)
{
uint16_t value = ADC_ReadValue(0);
LONGS_EQUAL(512, value);
}

View file

@ -3,6 +3,8 @@
//ImportTestGroups //ImportTestGroups
IMPORT_TEST_GROUP(simple_test); IMPORT_TEST_GROUP(simple_test);
IMPORT_TEST_GROUP(test_ADC);
IMPORT_TEST_GROUP(test_RegEdit);
//START: main //START: main
int main(int argc, char** argv) int main(int argc, char** argv)

View file

@ -1,7 +1,14 @@
project(Tests) project(Tests)
# TEST_DIRS # TEST_DIRS
add_subdirectory(MockRegEdit)
add_subdirectory(RegEdit)
add_subdirectory(simple_test) add_subdirectory(simple_test)
add_subdirectory(ADC)
add_subdirectory(MockADC)
# TEST_RUNNER # TEST_RUNNER
add_executable(AllTests add_executable(AllTests
@ -12,5 +19,18 @@ target_link_libraries(AllTests
${CPPUTEST_LIBRARIES}/libCppUTest.a ${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a ${CPPUTEST_LIBRARIES}/libCppUTestExt.a
# TEST_LINKS # TEST_LINKS
test_ADC
test_RegEdit
simple_test simple_test
) )
add_executable(Mock_Tests
MockTests.cpp
)
target_link_libraries(Mock_Tests
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
test_MockRegEdit
test_MockADC
)

View file

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

View file

@ -0,0 +1,94 @@
/*
* Author: Jake G
* Date: 2024
* filename: test_MockADC.c
* description:
*/
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTestExt/MockSupport.h"
#include <cstdint>
extern "C"
{
#include "MockADC.h"
}
TEST_GROUP(test_MockADC)
{
void setup()
{
}
void teardown()
{
mock().checkExpectations();
mock().clear();
}
};
TEST(test_MockADC, ADC_InitExpects)
{
mock().expectOneCall("ADC_Init")
.withUnsignedIntParameter("pin_num", 7);
ADC_Init(7);
}
TEST(test_MockADC, ADC_EnableExpects)
{
mock().expectOneCall("ADC_Enable");
ADC_Enable();
}
TEST(test_MockADC, ADC_DisableExpect)
{
mock().expectOneCall("ADC_Disable");
ADC_Disable();
}
TEST(test_MockADC, ADC_ReadValue)
{
MockADC_ZeroIndex();
MockADC_PushValue(512);
mock().expectOneCall("ADC_ReadValue_Impl")
.withUnsignedIntParameter("pin_num", 0x2);
uint16_t val = ADC_ReadValue(0x2);
LONGS_EQUAL(512, val);
}
TEST(test_MockADC, ADC_ReadValueReturnsZeroOnEmptyBuffer)
{
MockADC_ZeroIndex();
mock().expectOneCall("ADC_ReadValue_Impl")
.withUnsignedIntParameter("pin_num", 0x2)
.andReturnValue(0x0000);
uint16_t val = ADC_ReadValue(0x2);
LONGS_EQUAL(0, val);
}
TEST(test_MockADC, MockADC_PushValueDoesntOverflowArray)
{
MockADC_ZeroIndex();
for(int i = 0; i < 257; i++){
MockADC_PushValue(512+i);
CHECK_TRUE(MockADC_GetIndex() <= 255);
}
}
TEST(test_MockADC, MockADC_SetupSetsGlobal)
{
CHECK_FALSE(MockADC_IsSetup());
ADC_Setup();
CHECK_TRUE(MockADC_IsSetup());
}

View file

@ -0,0 +1,11 @@
# TEST_RUNNER
add_library(test_MockRegEdit
test_MockRegEdit.cpp
)
target_link_libraries(test_MockRegEdit
${CPPUTEST_LIBRARIES}/libCppUTest.a
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
MockRegEdit
)

View file

@ -0,0 +1,168 @@
/*
* Author: username
* Date: todays_date
* filename: test_MockRegEdit.c
* description: module_purpose
*/
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTestExt/MockSupport.h"
#include <cstdint>
extern "C"
{
#include "MockRegEdit.h"
}
TEST_GROUP(test_MockRegEdit)
{
void setup()
{
}
void teardown()
{
mock().clear();
}
};
TEST(test_MockRegEdit, RegEdit_ClearRegisterExpectedCallPasses)
{
uint8_t a;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_ClearRegister")
.withPointerParameter("reg", b);
RegEdit_ClearRegister(b);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_SetRegisterExpectedCallPasses)
{
uint8_t a;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_SetRegister")
.withPointerParameter("reg", b);
RegEdit_SetRegister(b);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_SetBitExpectedCallPasses)
{
uint8_t a;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_SetBit")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("bit_num", 5);
RegEdit_SetBit(b, 5);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_ClearBitExpectedCallPasses)
{
uint8_t a;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_ClearBit")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("bit_num", 5);
RegEdit_ClearBit(b, 5);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_IsBitSetExpectedCallPasses)
{
uint8_t a = 0xFF;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_IsBitSet")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("bit_num", 5)
.andReturnValue(true);
CHECK_TRUE(RegEdit_IsBitSet(b, 5));
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_IsBitSetExpectedCallPassesWithFalse)
{
uint8_t a = 0xFF;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_IsBitSet")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("bit_num", 5)
.andReturnValue(false);
CHECK_FALSE(RegEdit_IsBitSet(b, 5));
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_OR_NumExpectedWorks)
{
uint8_t a = 0xFF;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_OR_Num")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("num", 0x4)
.andReturnValue(false);
RegEdit_OR_Num(b, 0x4);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_SetNumPasses)
{
uint32_t a = 0xFFFFFFFF;
uint32_t *b = &a;
mock().expectOneCall("RegEdit_SetNum")
.withPointerParameter("reg", b)
.withUnsignedIntParameter("num", 0x4)
.andReturnValue(false);
RegEdit_SetNum(b, 0x4);
mock().checkExpectations();
}
TEST(test_MockRegEdit, RegEdit_ReadRegPasses)
{
uint8_t a = 0xFF;
uint8_t *b = &a;
mock().expectOneCall("RegEdit_ReadReg")
.withPointerParameter("reg", b)
.andReturnValue(0xFF);
uint8_t reg_val = RegEdit_ReadReg(b);
LONGS_EQUAL(0xFF, reg_val);
mock().checkExpectations();
}

13
tests/MockTests.cpp Normal file
View file

@ -0,0 +1,13 @@
#include "CppUTest/CommandLineTestRunner.h"
//ImportTestGroups
IMPORT_TEST_GROUP(test_MockRegEdit);
IMPORT_TEST_GROUP(test_MockADC);
//START: main
int main(int argc, char** argv)
{
return RUN_ALL_TESTS(argc, argv);
}
//END: main

View file

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

View file

@ -0,0 +1,32 @@
/*
* Author: username
* Date: todays_date
* filename: test_RegEdit.c
* description: module_purpose
*/
#include "CppUTest/CommandLineTestRunner.h"
extern "C"
{
#include "RegEdit.h"
}
TEST_GROUP(test_RegEdit)
{
void setup()
{
}
void teardown()
{
}
};
TEST(test_RegEdit, FirstTest)
{
//FAIL("Fail me!");
CHECK(true);
}