Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rework low-level hardware access #158

Merged
merged 9 commits into from
Sep 18, 2021
Merged

Conversation

stnolting
Copy link
Owner

@stnolting stnolting commented Sep 17, 2021

This PR is a complete makeover of the processor's C-language low-level hardware access. Instead of the current single-pointer approach a struct-based approach is used (https://blog.feabhas.com/2019/01/peripheral-register-access-using-c-structs-part-1/). The new approach is more intuitive and also more efficient as accesses to registers within the same unit can be computed from the module's base address and a simple offset (done by the compiler; it does not need to reload/reconstruct the whole 32-bit address).

This PR is used to gather all the modifications (for easy referencing changes). Once everything is converted, tested and documented, this PR will be merged 😉

Old Version (Current State)

In the current state memory-mapped registers are defined as single pointers and are accessed via pre-defined #defines:

#define SPI_BASE (0xFFFFFFA8UL) // /**< SPI base address */
#define SPI_SIZE (2*4) // /**< SPI address space size in bytes */

/** SPI control register (r/w) */
#define SPI_CT  (*(IO_REG32 (SPI_BASE + 0)))
/** SPI receive/transmit data register (r/w) */
#define SPI_DATA (*(IO_REG32 (SPI_BASE + 4)))

C-example program:

SPI_CT = 0x12345678;
uint32_t tmp = SPI_DATA;

New Version

The reworked version uses pre-defined structs to provide easier access to all memory-mapped interface registers of peripheral modules. Each module has it's own struct where the unit's interface registers are defined as members of this struct:

/** SPI module prototype */
typedef struct __attribute__((packed,aligned(4))) {
	uint32_t CTRL;  /**< offset 0: control register (#NEORV32_SPI_CTRL_enum) */
	uint32_t DATA;  /**< offset 4: data register */
} neorv32_spi_t;

/** SPI module hardware access (#neorv32_spi_t) */
#define NEORV32_SPI (*((volatile neorv32_spi_t*) (0xFFFFFFA8UL)))

C-example program:

NEORV32_SPI.CTRL = 0x12345678;
uint32_t tmp = NEORV32_SPI.DATA;

This also allows to do nice things like determining a module's address space size via sizeof(NEORV32_SPI).

Compatibility

A new file neorv32_legacy.h is added to the sw/lib/include folder that provides the "old" #define-based register names (mapping to the new structs) to provide backward compatibility for existing software.

Misc

This PR also renames the pre-defined control register names and bits: *CT* -> *CTRL*
Furthermore, theneorv32_cpu_delay_ms function is reworked to use MTIME by default for busy wait. If MTIME is not available (not implemented) the old ASM-based delay loop is used as fall-back.

instead of single "define" pointers
@stnolting stnolting added the enhancement New feature or request label Sep 17, 2021
@stnolting stnolting self-assigned this Sep 17, 2021
@stnolting stnolting added the DOC Improvements or additions to documentation label Sep 17, 2021
@umarcor umarcor marked this pull request as draft September 17, 2021 16:56
@stnolting stnolting marked this pull request as ready for review September 18, 2021 21:34
@stnolting stnolting merged commit 9d3fc2e into master Sep 18, 2021
@stnolting stnolting deleted the rework_low_level_hw_access branch September 18, 2021 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DOC Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant