Skip to content

Commit

Permalink
Merge pull request #39 from MEGA65/reduce-warnings
Browse files Browse the repository at this point in the history
Add tests to cc65 build as well as fileio test
  • Loading branch information
mlund authored Jul 31, 2023
2 parents bc04f61 + 288401d commit 0f7bdab
Show file tree
Hide file tree
Showing 25 changed files with 376 additions and 164 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Build using cc65
working-directory: ${{github.workspace}}
run: USE_LOCAL_CC65=1 make -f Makefile_cc65
run: USE_LOCAL_CC65=1 make -f Makefile_cc65 all

- name: Install llvm-mos-sdk
working-directory: ${{github.workspace}}
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# PRG files
*.prg
tests/*.prg

# Prerequisites
*.d

Expand Down
41 changes: 33 additions & 8 deletions Makefile_cc65
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@

SHELL:=/bin/bash
XEMU=xmega65
TESTS_DIR := tests
TESTS_SRCS := $(wildcard $(TESTS_DIR)/*.c)
TESTS_PRGS := $(TESTS_SRCS:.c=.prg)

ifdef USE_LOCAL_CC65
# use locally installed binary (requires 'cc65,ld65,etc' to be in the $PATH)
Expand All @@ -10,10 +14,11 @@ else
endif

CC65=$(CC65_PREFIX)cc65
CL65=$(CC65_PREFIX)cl65
CA65=$(CC65_PREFIX)ca65 --cpu 4510
AR65=$(CC65_PREFIX)ar65

CFLAGS=-O -t c64 -W +unused-param,+error,+unused-label,+no-effect,+unused-var,+no-effect -I include/
CFLAGS=-O -t c64 -I include/

LIB_OBJECTS = \
src/cc65/dirent.o \
Expand All @@ -32,21 +37,20 @@ LIB_OBJECTS = \
src/tests.o \
src/time.o

.PHONY: all clean cleanall
.PHONY: all clean cleanall test

all: libmega65.a
all: libmega65.a ${TESTS_PRGS}

libmega65.a: $(LIB_OBJECTS)
$(AR65) a $@ $^

clean:
rm -f src/*.o
rm -f src/cc65/*.o
rm -f $(LIB_OBJECTS) $(TESTS_PRGS) tests/*.o
rm -rf work

cleanall: clean
rm -f libmega65.a

libmega65.a: $(LIB_OBJECTS)
$(AR65) a $@ $^

src/cc65/%.o: src/cc65/%.s
$(CA65) -o $@ $<

Expand All @@ -56,3 +60,24 @@ src/%.o: src/%.c
fi
$(CC65) $(CFLAGS) -o work/$*.s $<
$(CA65) -o $@ work/$*.s

# Unit tests using Xemu in "testing" mode
#
# - Xemu `xmega65` must be in your path
# - Xemu's return code is controlled by register 0xD6CF
# - All tests are in the `tests/` directory
tests/%.prg: tests/%.c libmega65.a
$(CL65) $(CFLAGS) $< -o $@ libmega65.a
test: | $(TESTS_PRGS)
@if ! command -v $(XEMU) &> /dev/null; then \
echo "Cannot run tests as xmega65 (Xemu) is not in your path."; \
else \
for test in $(TESTS_PRGS); do \
if $(XEMU) -testing -sleepless -headless -model 3 -prg $$test &> /dev/null; then \
echo "Test passed: $$test"; \
else \
echo "Test FAILED: $$test"; \
fi; \
done; \
fi

16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,23 @@ Simple C library for the MEGA65
## Clang

1. Install [llvm-mos-sdk](https://github.com/llvm-mos/llvm-mos-sdk#getting-started).
This e.g. downloads for linux and unpacks into `$HOME/llvm-mos`:
~~~ sh
wget https://github.com/llvm-mos/llvm-mos-sdk/releases/latest/download/llvm-mos-linux.tar.xz
tar xf llvm-mos-linux.tar.xz -C $HOME
~~~
2. Configure and make with:
~~~ sh
cmake -DCMAKE_PREFIX_PATH=<llvm-mos-sdk-install-prefix> -B build/ mega65-libc/
cd build/
cmake -DCMAKE_PREFIX_PATH=$HOME/llvm-mos -B build/ mega65-libc/
cd build
make
make test # if `xmega65` (Xemu) is in your path
make test # if `xmega65` (Xemu) was in your patch when running cmake
~~~

### Dependent CMake projects
### Dependent projects

`CMakeLists.txt` of a dependent project could look like this:
It's trivial to write a classic `Makefile` for clang.
For dependent CMake based projects, `CMakeLists.txt` could look like this:
~~~ cmake
cmake_minimum_required(VERSION 3.5)
set(LLVM_MOS_PLATFORM mega65)
Expand Down
6 changes: 5 additions & 1 deletion include/mega65/debug.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef __MEGA65_DEBUG_H
#define __MEGA65_DEBUG_H

void debug_msg(char* m);
/**
* @brief Write debug message to serial monitor
* @param msg Text message to write
*/
void debug_msg(char* msg);

#endif // __MEGA65_DEBUG_H
16 changes: 11 additions & 5 deletions include/mega65/dirent.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@

#include <stdint.h>

/// Open a directory
unsigned char opendir(void);

/// Read directory entry
struct m65_dirent* readdir(unsigned char);

/// Close directory entry
void closedir(unsigned char);

/// Structure describing an open directory
#ifdef __clang__
struct __attribute__((__packed__)) m65_dirent {
#else
struct m65_dirent {
#endif
uint32_t d_ino;
uint16_t d_off;
uint32_t d_reclen;
uint16_t d_type;
char d_name[256];
uint32_t d_ino; //!< File number of entry
uint16_t d_off; //!< Offset
uint32_t d_reclen; //!< Length of this record
uint16_t d_type; //!< File type
char d_name[256]; //!< Filename string of entry
};

#endif // __MEGA65_DIRENT_H
10 changes: 4 additions & 6 deletions include/mega65/fcio.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@

/*! @file fcio.h
@brief Full colour mode i/o library for the MEGA65
Details.
*/
/**
* @file fcio.h
* @brief Full colour mode i/o library for the MEGA65
*/

#ifndef __MEGA65_FCIO_H
#define __MEGA65_FCIO_H
Expand Down
48 changes: 36 additions & 12 deletions include/mega65/fileio.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
#ifndef __MEGA65_FILEIO_H
#define __MEGA65_FILEIO_H

void toggle_rom_write_protect();
#include <stdint.h>
#include <stddef.h>

void toggle_rom_write_protect(void);

/** Closes all open files */
void closeall(void);
void close(unsigned char fd);

// Returns file descriptor
unsigned char open(char* filename);
/**
* @brief Close a single file
* @param fd File descriptor pointing to file to close
*/
void close(uint8_t fd);

/**
* @brief Open file
* @param filename to open
* @return File descriptor or `0xff` if error
*/
uint8_t open(char* filename);

// Read upto one sector of data into the supplied buffer.
// Returns the number of bytes actually read.
unsigned short read512(unsigned char* buffer);
/**
* @brief Read up to 512 bytes from file
* @param buffer Input buffer
* @return Number of bytes read
*/
size_t read512(uint8_t* buffer);

// Change working directory
// (only accepts one directory segment at a time
unsigned char chdir(char* filename);
/**
* @brief Change working directory
* @param filename Directory name
* @return Error code (currently unused)
* @note Only accepts one directory segment at a time
*/
uint8_t chdir(char* filename);

// Change working directory to the root directory
unsigned char chdirroot(void);
/**
* @brief Change working directory to the root directory
* @return Error code (currently unused)
*/
uint8_t chdirroot(void);

#endif // __MEGA65_FILEIO_H
4 changes: 4 additions & 0 deletions include/mega65/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#include <stdint.h>

/**
* @brief Sleep for the given number of microseconds
* @param micros Microseconds to sleep
*/
void usleep(uint32_t micros);

#endif // __MEGA65_HAL_H
63 changes: 59 additions & 4 deletions include/mega65/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
#define __MEGA65_MEMORY_H

#include <stdint.h>
#include <stddef.h>

#define DMA_COPY_CMD 0x00;
#define DMA_FILL_CMD 0x03;

/**
* @brief DMA list structure
*/
#ifdef __clang__
struct __attribute__((__packed__)) dmagic_dmalist {
#else
Expand Down Expand Up @@ -37,17 +44,65 @@ extern struct dmagic_dmalist dmalist;
extern uint8_t dma_byte;
#endif

/**
* @brief Enable Mega65 mode
*/
void mega65_io_enable(void);

/**
* @brief Peek a byte from the given address
* @param address 28-bit address
* @return uint8_t with the value at the given address
*/
uint8_t lpeek(uint32_t address);
uint8_t lpeek_debounced(uint32_t address);

/**
* @brief Peek a byte from the given address using DMA copy
* @param address 28-bit address
* @return Single byte from the given address
*/
uint8_t dma_peek(uint32_t address);

/**
* @brief Poke a byte to the given address
* @param address 28-bit address
* @param value Single byte to write to the given address
*/
void lpoke(uint32_t address, uint8_t value);

/**
* @brief Poke a byte to the given address using DMA copy
* @param address 28-bit address
* @param value Single byte to write to the given address
*/
void dma_poke(uint32_t address, uint8_t value);
void lcopy(
uint32_t source_address, uint32_t destination_address, uint16_t count);
void lfill(uint32_t destination_address, uint8_t value, uint16_t count);

/**
* @brief Copy a block of memory using DMA
* @param source_address 28-bit address to copy from
* @param destination_address 28-bit address to copy to
* @param count Number of bytes to copy
*/
void lcopy(uint32_t source_address, uint32_t destination_address, size_t count);

/**
* @brief Fill a block of memory with a single byte using DMA
* @param destination_address Start address (28-bit)
* @param value Fill value
* @param count Number of bytes to fill
*/
void lfill(uint32_t destination_address, uint8_t value, size_t count);

/**
* @brief Fill a block of memory with a single byte using DMA with a step
* @param destination_address Start address (28-bit)
* @param value Fill value
* @param count Number of bytes to fill
* @param skip Skip every n bytes
*/
void lfill_skip(
uint32_t destination_address, uint8_t value, uint16_t count, uint8_t skip);
uint32_t destination_address, uint8_t value, size_t count, uint8_t skip);

#ifdef __clang__
#define POKE(X, Y) (*(volatile uint8_t*)(X)) = Y
Expand Down
6 changes: 5 additions & 1 deletion include/mega65/targets.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef __MEGA65_TARGETS_H
#define __MEGA65_TARGETS_H

#include <stdint.h>

#define TARGET_UNKNOWN 0
#define TARGET_MEGA65R1 1
#define TARGET_MEGA65R2 2
Expand All @@ -12,7 +14,9 @@
#define TARGET_NEXYS4DDRWIDGET 0x42
#define TARGET_WUKONG 0xFD
#define TARGET_SIMULATION 0xFE
#define TARGET_EMULATION 0xFF //!< Emulator like Xemu

unsigned char detect_target(void);
/// Detects the target on which we're running
uint8_t detect_target(void);

#endif // __MEGA65_TARGETS_H
11 changes: 11 additions & 0 deletions include/mega65/tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
#define TEST_LOG 0xfd
#define TEST_SETNAME 0xfe
#define TEST_DONEALL 0xff
#define XEMU_CONTROL 0xD6CF
#define XEMU_QUIT 0x42

/**
* @brief Quits Xemu with given exit code
* @param exit_code Exit code passed to Xemu, e.g. EXIT_SUCCESS or EXIT_FAILURE
*
* Xemu must be run in `-testing` mode for this to have any effect and
* also make sure to call `mega65_io_enable()` before calling this function.
*/
void xemu_exit(int exit_code);

// convenience methods

Expand Down
2 changes: 2 additions & 0 deletions include/mega65/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ struct m65_tm {
unsigned char tm_isdst; /* Daylight saving time */
};

/// Get real-time clock
void getrtc(struct m65_tm* tm);
/// Set real-time clock
void setrtc(struct m65_tm* tm);

#endif // __MEGA65_TIME_H
Loading

0 comments on commit 0f7bdab

Please sign in to comment.