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

Add MCX N94x multidrv #508

Merged
merged 1 commit into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions _targets/Makefile.armv8m33-mcxn94x
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# Makefile for Phoenix-RTOS 3 device drivers
#
# MCX N94x drivers
#
# Copyright 2019, 2020, 2024 Phoenix Systems
#

DEFAULT_COMPONENTS := mcxn94x-multi
15 changes: 15 additions & 0 deletions multi/mcxn94x-multi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Makefile for Phoenix-RTOS mcxn94x-multi
#
# Copyright 2024 Phoenix Systems
#

NAME := mcxn94x-multi

LOCAL_PATH := $(call my-dir)

LOCAL_SRCS = mcxn94x-multi.c dev.c uart.c dummyfs.c
DEP_LIBS := libtty libklog libpseudodev
LIBS := libdummyfs libklog libpseudodev libposixsrv

include $(binary.mk)
43 changes: 43 additions & 0 deletions multi/mcxn94x-multi/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Phoenix-RTOS
*
* MCX N94x common
*
* Copyright 2017, 2018, 2024 Phoenix Systems
* Author: Aleksander Kaminski, Hubert Buczynski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#ifndef _COMMON_H_
#define _COMMON_H_

#include <arch.h>
#include <board_config.h>
#include <phoenix/arch/armv8m/mcx/n94x/mcxn94x.h>


#define NELEMS(x) (sizeof(x) / sizeof(*(x)))


static inline void common_dataBarrier(void)
{
__asm__ volatile ("dmb");
agkaminski marked this conversation as resolved.
Show resolved Hide resolved
}


static inline void common_dataSyncBarrier(void)
{
__asm__ volatile ("dsb");
agkaminski marked this conversation as resolved.
Show resolved Hide resolved
}


static inline void common_instrBarrier(void)
{
__asm__ volatile ("isb");
agkaminski marked this conversation as resolved.
Show resolved Hide resolved
}


#endif
102 changes: 102 additions & 0 deletions multi/mcxn94x-multi/dev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Phoenix-RTOS
*
* Multidriver device manager
*
* Copyright 2024 Phoenix Systems
* Author: Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <stddef.h>
#include <errno.h>
#include <sys/msg.h>
#include <posix/utils.h>

#include "common.h"
#include "dev.h"


#define MAJOR_MAX 16


static struct {
oid_t oid;
devHandler *devices[MAJOR_MAX];
} dev_common = { .devices = { NULL } };


static void dev_oid2mm(oid_t *oid, unsigned int *major, unsigned int *minor)
{
*major = (oid->id >> 16) & 0xffff;
*minor = oid->id & 0xffff;
}


static void dev_mm2oid(oid_t *oid, unsigned int major, unsigned int minor)
{
oid->id = (major << 16) | minor;
}


/* To be used only in constructors - no lock needed */
int dev_allocMajor(unsigned int *major)
{
static unsigned int counter = 0;

if (counter == NELEMS(dev_common.devices)) {
return -1;
}

*major = counter++;

return 0;
}


int dev_registerFile(const char *fname, unsigned int major, unsigned int minor)
{
oid_t oid = { .port = dev_common.oid.port };

dev_mm2oid(&oid, major, minor);

return create_dev(&oid, fname);
}


int dev_msgReceive(msg_t *msg, msg_rid_t *rid)
{
return msgRecv(dev_common.oid.port, msg, rid);
}


void dev_handle(msg_t *msg, msg_rid_t rid)
{
unsigned int major, minor;

dev_oid2mm(&msg->oid, &major, &minor);

if ((major < NELEMS(dev_common.devices)) && (dev_common.devices[major] != NULL)) {
dev_common.devices[major](msg, rid, major, minor);
}
else {
msg->o.err = -ENOSYS;
msgRespond(dev_common.oid.port, msg, rid);
}
}


void dev_register(devHandler *handler, unsigned int major)
{
dev_common.devices[major] = handler;
}


/* Has to be executed first! */
static void __attribute__((constructor(101))) dev_init(void)
{
portCreate(&dev_common.oid.port);
}
36 changes: 36 additions & 0 deletions multi/mcxn94x-multi/dev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Phoenix-RTOS
*
* Multidriver device manager
*
* Copyright 2024 Phoenix Systems
* Author: Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#ifndef MULTI_DEV_H_
#define MULTI_DEV_H_

#include <sys/msg.h>

typedef void devHandler(msg_t *msg, msg_rid_t rid, unsigned int major, unsigned int minor);


int dev_allocMajor(unsigned int *major);


int dev_registerFile(const char *fname, unsigned int major, unsigned int minor);


int dev_msgReceive(msg_t *msg, msg_rid_t *rid);


void dev_handle(msg_t *msg, msg_rid_t rid);


void dev_register(devHandler *handler, unsigned int major);

#endif /* MULTI_DEV_H_ */
184 changes: 184 additions & 0 deletions multi/mcxn94x-multi/dummyfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Phoenix-RTOS
*
* MCX N94x multi driver buit-in dummyds
*
* Copyright 2021, 2024 Phoenix Systems
* Author: Maciej Purski, Aleksander Kaminski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <board_config.h>

#if defined(BUILTIN_DUMMYFS) && BUILTIN_DUMMYFS != 0

#include <errno.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/msg.h>
#include <sys/threads.h>
#include <stdlib.h>

#include <phoenix/sysinfo.h>

#include <dummyfs.h>

static struct {
char stack[2048] __attribute__((aligned(8)));
unsigned port;
} dummy_common;


static int syspage_create(void *ctx, oid_t *root)
{
oid_t sysoid = { 0 };

int progsz = syspageprog(NULL, -1);
if (progsz < 0) {
return progsz;
}

if (dummyfs_create(ctx, root, "syspage", &sysoid, 0666, otDir, NULL) != 0) {
return -ENOMEM;
}

for (int i = 0; i < progsz; i++) {
syspageprog_t prog;
oid_t toid;

if (syspageprog(&prog, i) != 0) {
continue;
}

dummyfs_createMapped(ctx, &sysoid, prog.name, (void *)prog.addr, prog.size, &toid);
}

return 0;
}


static void msgthr(void *ctx)
{
msg_t msg;
msg_rid_t rid;

for (;;) {
if (msgRecv(dummy_common.port, &msg, &rid) < 0) {
continue;
}

switch (msg.type) {

case mtOpen:
msg.o.err = dummyfs_open(ctx, &msg.oid);
break;

case mtClose:
msg.o.err = dummyfs_close(ctx, &msg.oid);
break;

case mtRead:
msg.o.err = dummyfs_read(ctx, &msg.oid, msg.i.io.offs, msg.o.data, msg.o.size);
break;

case mtWrite:
msg.o.err = dummyfs_write(ctx, &msg.oid, msg.i.io.offs, msg.i.data, msg.i.size);
break;

case mtTruncate:
msg.o.err = dummyfs_truncate(ctx, &msg.oid, msg.i.io.len);
break;

case mtDevCtl:
msg.o.err = -ENOSYS;
break;

case mtCreate:
msg.o.err = dummyfs_create(ctx, &msg.oid, msg.i.data, &msg.o.create.oid, msg.i.create.mode, msg.i.create.type, &msg.i.create.dev);
break;

case mtDestroy:
msg.o.err = dummyfs_destroy(ctx, &msg.oid);
break;

case mtSetAttr:
msg.o.err = dummyfs_setattr(ctx, &msg.oid, msg.i.attr.type, msg.i.attr.val, msg.i.data, msg.i.size);
break;

case mtGetAttr:
msg.o.err = dummyfs_getattr(ctx, &msg.oid, msg.i.attr.type, &msg.o.attr.val);
break;

case mtGetAttrAll: {
struct _attrAll *attrs = msg.o.data;
if ((attrs == NULL) || (msg.o.size < sizeof(struct _attrAll))) {
msg.o.err = -EINVAL;
break;
}
msg.o.err = dummyfs_getattrAll(ctx, &msg.oid, attrs);
break;
}

case mtLookup:
msg.o.err = dummyfs_lookup(ctx, &msg.oid, msg.i.data, &msg.o.lookup.fil, &msg.o.lookup.dev);
break;

case mtLink:
msg.o.err = dummyfs_link(ctx, &msg.oid, msg.i.data, &msg.i.ln.oid);
break;

case mtUnlink:
msg.o.err = dummyfs_unlink(ctx, &msg.oid, msg.i.data);
break;

case mtReaddir:
msg.o.err = dummyfs_readdir(ctx, &msg.oid, msg.i.readdir.offs, msg.o.data, msg.o.size);
break;

default:
msg.o.err = -EINVAL;
break;
}
msgRespond(dummy_common.port, &msg, rid);
}
}


void __attribute__((constructor(102))) dummyfs_init(void)
{
void *ctx;
oid_t root = { 0 };

if (portCreate(&dummy_common.port) != 0) {
return;
}

if (portRegister(dummy_common.port, "/", &root) != 0) {
portDestroy(dummy_common.port);
return;
}

root.port = dummy_common.port;
if (dummyfs_mount(&ctx, NULL, 0, &root) != 0) {
printf("dummyfs mount failed\n");
portDestroy(dummy_common.port);
return;
}

if (syspage_create(ctx, &root) != 0) {
dummyfs_unmount(ctx);
portDestroy(dummy_common.port);
return;
}

if (beginthread(msgthr, 4, dummy_common.stack, sizeof(dummy_common.stack), ctx) != 0) {
dummyfs_unmount(ctx);
portDestroy(dummy_common.port);
return;
}
}

#endif /* BUILTIN_DUMMYFS */
Loading
Loading