vxkernel - v0.7.0-5 : setup libSSP (WIP) + support USB description step (WIP)

*add*
> [cpu]
  | add SH-CPU context structure
  | try to support Stack-Protector but seems not insert check during compile-time
  | add stack abord routine invocation (WIP)
> [usb]
  | add configuration structure
  | add configuration handling
  | add USB logger (WIP)
  | add USB high-level abstraction for debugging (WIP)
  | add USB driver
  | add fake SDL2 USB driver

*update*
> [usb]
  | clean DCP configuration API (WIP)
  | prepare proper pipe handling (WIP)
  | isolate USB protocole initialisation
  | enable some interruption
> [vxsdk.toml]
  | force enable libSSP (but seems not work o(x_x)o)

*fix*
> [usb]
  | fix endpoint type ID
> [display]
  | [dtext] workaround to possible stack corruption (WIP)
> [hypervisor]
  | [switch] fix NULL power primitives
> [vxdev]
  | use `/usr/bin/env python3` instead of `python3`
This commit is contained in:
Yann MAGNIN 2023-04-03 10:52:05 +02:00
parent c6aa4b5ac4
commit 18e895dfb7
34 changed files with 830 additions and 314 deletions

View File

@ -6,32 +6,35 @@
# define __VHEX_DEFS_ATTRIBUTES__
/* Objects from specific sections */
#define VSECTION(x) __attribute__((section(x)))
#define VSECTION(x) __attribute__((section(x)))
/* Disable Stack Protector */
#define VNO_STACK_PROTECTOR __attribute__((no_stack_protector))
/* Unused parameters or variables */
#define VUNUSED __attribute__((unused))
#define VUNUSED __attribute__((unused))
/* Functions that *must* be inlined */
#define VINLINE __attribute__((always_inline)) inline
#define VINLINE __attribute__((always_inline)) inline
/* Aligned variables */
#define VALIGNED(x) __attribute__((aligned(x)))
#define VALIGNED(x) __attribute__((aligned(x)))
/* Packed structures. I require explicit alignment because if it's unspecified,
GCC cannot optimize access size, and reads to memory-mapped I/O with invalid
access sizes silently fail - honestly you don't want this to happen */
#define VPACKED(x) __attribute__((packed, aligned(x)))
#define VPACKED(x) __attribute__((packed, aligned(x)))
/* Packed enumerations */
#define VPACKED_ALONE __attribute__((packed))
#define VPACKED_ALONE __attribute__((packed))
/* Transparent unions */
#define VTRANSPARENT __attribute__((transparent_union))
#define VTRANSPARENT __attribute__((transparent_union))
/* Weak symbols */
#define VWEAK __attribute__((weak))
#define VWEAK __attribute__((weak))
/* Constructors */
#define VCONSTRUCTOR __attribute__((constructor))
#define VDESTRUCTOR __attribute__((destructor))
#define VCONSTRUCTOR __attribute__((constructor))
#define VDESTRUCTOR __attribute__((destructor))
/* Functions that do not return */
#define VNORETURN __attribute__((noreturn))
#define VNORETURN __attribute__((noreturn))
#endif /*__VHEX_DEFS_ATTRIBUTES__*/

View File

@ -4,6 +4,21 @@
#include <vhex/defs/types.h>
#include <vhex/defs/attributes.h>
//---
// Complet CPU contexte
//---
struct sh7305_cpu_ctx {
uintptr_t pr;
uintptr_t spc;
uintptr_t ssr;
uintptr_t mach;
uintptr_t macl;
uintptr_t gbr;
uintptr_t sgr;
uintptr_t r[16];
};
//---
// Access to CPU registers
//---

View File

@ -468,20 +468,28 @@ extern void sh7305_usb_interrupt_handler(void);
/* sh7305_usb_request_handle() : handle USB request */
extern void sh7305_usb_request_handle(void);
#include <vhex/usb/device.h>
#include <vhex/usb/configuration.h>
/* sh7305_usb_open() : power on the module and setup USB module */
extern int sh7305_usb_open(struct usb_full_device *device);
/* sh7305_configuration_resolve() : check and resolve USB configuration */
extern int sh7305_usb_configuration_resolve(struct usb_full_device *device);
/* sh7305_pipe_find() : try to find a pipe */
extern int sh7305_usb_pipe_find(int type);
/* sh7305_usb_dcp_prepare() : prepare FIFO buffer */
extern void sh7305_usb_dcp_prepare(void);
/* sh7305_usb_dcp_write() : send data through DCP pipe */
extern int sh7305_usb_dcp_write(void *buffer, size_t n);
/* sh7305_usb_dcp_commit() : send data */
extern void sh7305_usb_dcp_commit(void);
//---
// Utils
//---

View File

@ -1 +1,2 @@
#include <vhex/usb/logger.h>
#include <vhex/usb/primitives.h>

View File

@ -0,0 +1,60 @@
#ifndef __VHEX_USB_CONFIGURATION_H__
#define __VHEX_USB_CONFIGURATION_H__ 1
#include <vhex/usb/descriptor.h>
/* usb_full_interface - interface descriptor, names, and endpoints */
struct usb_full_interface {
usb_dc_interf_t *descriptor;
char **strs;
usb_dc_endpnt_t **endpoint;
};
/* usb_full_config - interface descriptor, names, and interfaces */
struct usb_full_config {
usb_dc_config_t *descriptor;
char **strs;
struct usb_full_interface **interface;
};
/* usb_full_device - interface descriptor, names, and configurations */
struct usb_full_device {
usb_dc_device_t *descriptor;
char **strs;
struct usb_full_config **config;
};
/* __USB_MAX_* - internal configuration limit */
#define __USB_MAX_DC_CONF 2
#define __USB_MAX_DC_INTR 4
#define __USB_MAX_DC_ENDP 9
/* usb_config_resolve() : check and resolve USB configuration */
extern int usb_config_resolve(struct usb_full_device *device);
/* usb_config_select_config() : try to selecte a configuration */
extern int usb_config_select_config(int idx);
/* usb_config_get_dc_device() : get device descriptor */
extern int usb_config_get_dc_device(usb_dc_device_t **dc_device, int idx);
/* usb_config_get_dc_config() : get config descriptor */
extern int usb_config_get_dc_config(
usb_dc_config_t **dc_config,
int idx,
int *isidx,
int *ieidx
);
/* usb_config_get_dc_interf() : get interface descriptor */
extern int usb_config_get_dc_interf(
usb_dc_interf_t **dc_interf,
int idx,
int *esidx,
int *eeidx
);
/* usb_config_get_dc_endpoint() : get endpoint descriptor */
extern int usb_config_get_dc_endpnt(usb_dc_endpnt_t **dc_endpoint, int idx);
#endif /* __VHEX_USB_CONFIGURATION_H__ */

View File

@ -0,0 +1,15 @@
#ifndef __VHEX_USB_DESCRIPTOR_H__
#define __VHEX_USB_DESCRIPTOR_H__ 1
#include <vhex/usb/descriptor/device.h>
#include <vhex/usb/descriptor/configuration.h>
#include <vhex/usb/descriptor/interface.h>
#include <vhex/usb/descriptor/endpoint.h>
/* usb_dc_* - create kernel aliases */
typedef struct usb_descriptor_device usb_dc_device_t;
typedef struct usb_descriptor_configuration usb_dc_config_t;
typedef struct usb_descriptor_interface usb_dc_interf_t;
typedef struct usb_descriptor_endpoint usb_dc_endpnt_t;
#endif /* __VHEX_USB_DESCRIPTOR_H__ */

View File

@ -30,8 +30,11 @@ struct usb_descriptor_configuration {
uint8_t bMaxPower;
} VPACKED_ALONE;
//---
// Helpers
//---
#include <vhex/usb/descriptor/types.h>
#include <vhex/usb/utils.h>
/* USB_DECLARE_DESC_CONF - helper to declare configuration descriptor */
#define USB_DECLARE_DESC_CONF(name, ...) \

View File

@ -14,15 +14,18 @@ struct usb_descriptor_device {
uint8_t bMaxPacketSize0; /* packet size of endpoint 0 */
uint16_t idVendor; /* vendor ID (assigned by USB-IF) */
uint16_t idProduct; /* product ID (assigned by manufacturer) */
uint16_t bcdDevice; /* device release version (0x220 -> 2.220) */
uint16_t bcdDevice; /* device release version (0x220 -> 2.20) */
uint8_t iManufacturer; /* index of string descr. for Manufacturer */
uint8_t iProduct; /* index of string descr. for product */
uint8_t iSerialNumber; /* index of string descr. for serial number */
uint8_t bNumConfigurations;/* number of possible configuration */
} VPACKED_ALONE;
//---
// helpers
//---
#include <vhex/usb/descriptor/types.h>
#include <vhex/usb/utils.h>
/* USB_DECLARE_DESC_DEV - helper to declare device descriptor */
#define USB_DECLARE_DESC_DEVICE(name, ...) \
@ -34,7 +37,6 @@ struct usb_descriptor_device {
{ \
.bLengh = sizeof(struct usb_descriptor_device), \
.bDescriptorType = USB_DESCRIPTOR_DEVICE, \
.bcdUSB = USB_WORD_TO(0x200), \
__VA_ARGS__ \
}

View File

@ -43,8 +43,11 @@ struct usb_descriptor_endpoint {
uint8_t bInterval; /* Interval for polling endpoint */
} VPACKED_ALONE;
//---
// Helpers
//---
#include <vhex/usb/descriptor/types.h>
#include <vhex/usb/utils.h>
/* USB_DECLARE_DESC_ENDPOINT - helper to declare endpoint descriptor */
#define USB_DECLARE_DESC_ENDPOINT(name, ...) \

View File

@ -16,8 +16,11 @@ struct usb_descriptor_interface {
uint8_t iInterface; /* index of string desc. for this interface */
} VPACKED_ALONE;
//---
// Helpers
//---
#include <vhex/usb/descriptor/types.h>
#include <vhex/usb/utils.h>
/* USB_DECLARE_DESC_INTERFACE - helper to declare interface descriptor */
#define USB_DECLARE_DESC_INTERFACE(name, ...) \

View File

@ -4,6 +4,6 @@
#define USB_DESCRIPTOR_DEVICE 1
#define USB_DESCRIPTOR_CONFIGURATION 2
#define USB_DESCRIPTOR_INTERFACE 4
#define USB_DESCRIPTOR_ENDPOINT 7
#define USB_DESCRIPTOR_ENDPOINT 5
#endif /* __VHEX_USB_DESCRIPTOR_TYPES_H__ */

View File

@ -1,28 +0,0 @@
#ifndef __VHEX_USB_DEVICE_H__
#define __VHEX_USB_DEVICE_H__ 1
#include <vhex/defs/types.h>
#include <vhex/usb/descriptor/device.h>
#include <vhex/usb/descriptor/configuration.h>
#include <vhex/usb/descriptor/interface.h>
#include <vhex/usb/descriptor/endpoint.h>
struct usb_full_interface {
struct usb_descriptor_interface *descriptor;
char **strs;
struct usb_descriptor_endpoint **endpoint;
};
struct usb_full_config {
struct usb_descriptor_configuration *descriptor;
char **strs;
struct usb_full_interface **interface;
};
struct usb_full_device {
struct usb_descriptor_device *descriptor;
char **strs;
struct usb_full_config **config;
};
#endif /* __VHEX_USB_DEVICE_H__ */

View File

@ -0,0 +1,20 @@
#ifndef __VHEX_USB_INFO_H__
#define __VHEX_USB_INFO_H__ 1
#include <vhex/usb/interface.h>
#include <vhex/usb/logger.h>
/* internal USB module information */
struct usb_mod_info
{
struct usb_drv_interface driver;
struct {
bool attached;
usb_logger_t device;
} logger;
};
/* internaly used by the module */
extern struct usb_mod_info usb_mod_info;
#endif /* __VHEX_USB_INFO_H__ */

View File

@ -0,0 +1,15 @@
#ifndef __VHEX_USB_INTERFACE_H__
#define __VHEX_USB_INTERFACE_H__ 1
#include <vhex/usb/configuration.h>
struct usb_drv_interface
{
/* "classic" primitives API */
int (*open)(struct usb_full_device *device);
/* pipe API */
int (*pipe_find)(int type);
};
#endif /* __VHEX_USB_INTERFACE_H__ */

View File

@ -0,0 +1,7 @@
#ifndef __VHEX_USB_PIPE_H__
#define __VHEX_USB_PIPE_H__ 1
/* usb_pipe_find() - try to find a free pipe of type `type` (BULK, ...) */
extern int usb_pipe_find(int type);
#endif /* __VHEX_USB_PIPE_H__ */

View File

@ -0,0 +1,9 @@
#ifndef __VHEX_USB_PRIMITIVES_H__
#define __VHEX_USB_PRIMITIVES_H__ 1
#include <vhex/usb/configuration.h>
/* usb_open() : open primitive */
extern int usb_open(struct usb_full_device *device);
#endif /* __VHEX_USB_PRIMITIVES_H__ */

View File

@ -0,0 +1,37 @@
#include <vhex/usb/interface.h>
#include <vhex/driver.h>
#include <stdio.h>
static int sdl2_usb_open(void)
{
printf("SDL2 : USB driver not implemented\n");
return -1;
}
static int sdl2_usb_pipe_find(void)
{
return 0;
}
/* declare driver */
struct vhex_driver drv_usb = {
.name = "USB",
.hpowered = NULL,
.hpoweron = NULL,
.hpoweroff = NULL,
.hsave = NULL,
.hrestore = NULL,
.configure = NULL,
.state_size = 4,
.flags = {
.USB = 1,
.SHARED = 0,
.UNUSED = 1,
},
.module_data = &(struct usb_drv_interface){
.open = (void*)&sdl2_usb_open,
.pipe_find = (void*)&sdl2_usb_pipe_find
}
};
VHEX_DECLARE_DRIVER(06, drv_usb);

View File

@ -0,0 +1,52 @@
.text
.global ___stack_chk_guard
.global ___stack_chk_fail
.balign 4
___stack_chk_guard:
.long 0xdeb0cad0
.balign 4
___stack_chk_fail:
! Generate "CPU" context
sts.l pr, @-r15
stc.l spc, @-r15
stc.l ssr, @-r15
sts.l mach, @-r15
sts.l macl, @-r15
stc.l gbr, @-r15
stc.l sgr, @-r15
mov.l r14, @-r15
mov.l r13, @-r15
mov.l r12, @-r15
mov.l r11, @-r15
mov.l r10, @-r15
mov.l r9, @-r15
mov.l r8, @-r15
mov.l r7, @-r15
mov.l r6, @-r15
mov.l r5, @-r15
mov.l r4, @-r15
mov.l r3, @-r15
mov.l r2, @-r15
mov.l r1, @-r15
mov.l r0, @-r15
! invoke the panic handler, it SHOULD never return
mov.l sh7305_cpu_stack_chk_fail, r0
jsr @r0
mov r15, r4
! handle panic handler error
panic_handler_error:
bra panic_handler_error
nop
.balign 4
sh7305_cpu_stack_chk_fail:
.long _sh7305_cpu_stack_chk_fail

View File

@ -0,0 +1,27 @@
#include <vhex/defs/attributes.h>
#include <vhex/driver/mpu/sh/sh7305/cpu.h>
#include <vhex/display.h>
/* defined by the linker script */
extern uint32_t __kernel_reloc_start;
/* sh7305_cpu_stack_chk_fail() : stack smashing error */
VNO_STACK_PROTECTOR
void sh7305_cpu_stack_chk_fail(struct sh7305_cpu_ctx *ctx)
{
dclear(C_WHITE);
dtext(6, 3, C_BLACK, "Stack smashing detected (System ERROR)");
dtext( 6, 45, C_BLACK, "PC");
dprint(38, 45, C_BLACK, "= %08x", ctx->pr - (uintptr_t)&__kernel_reloc_start);
dtext(261, 45, C_BLACK, "(Error location)");
dprint( 6, 90, C_BLACK, "reloc base = %p", &__kernel_reloc_start);
dtext(6, 120, C_BLACK, "An unrecoverable error occurred in the add-in.");
dtext(6, 135, C_BLACK, "Please press the RESET button to restart the");
dtext(6, 150, C_BLACK, "calculator.");
dupdate();
while (1) { __asm__ volatile ("sleep"); }
}

View File

@ -1,9 +1,11 @@
#include <vhex/display.h>
#include <vhex/defs/types.h>
/* defined by the linker script */
extern uint32_t __kernel_reloc_start;
void sh7305_intc_exch_panic(void)
{
extern uint32_t __kernel_reloc_start;
uint32_t PC;
uint32_t TEA;
uint32_t TRA;
@ -14,7 +16,7 @@ void sh7305_intc_exch_panic(void)
TEA = *(volatile uint32_t *)0xff00000c;
TRA = *(volatile uint32_t *)0xff000020 >> 2;
code = *(volatile uint32_t*)0xff000024;
code = *(volatile uint32_t *)0xff000024;
dclear(C_WHITE);
dtext(6, 3, C_BLACK, "An exception occured! (System ERROR)");

View File

@ -1,150 +0,0 @@
#include <vhex/driver/mpu/sh/sh7305/usb.h>
#include <vhex/driver/cpu.h>
#include <vhex/usb.h>
#include <string.h>
//---
// Internals
//---
/* abitrary USB configuration limit (TODO : update me?) */
#define __SH7305_USB_MAX_DC_CONF 2
#define __SH7305_USB_MAX_DC_INTR 4
#define __SH7305_USB_MAX_DC_ENDP 9
/* internal copy of each descriptor (TODO : update me?) */
struct usb_descriptor_device __sh7305_usb_dc_device;
struct usb_descriptor_configuration __sh7305_usb_dc_conf[__SH7305_USB_MAX_DC_CONF];
struct usb_descriptor_interface __sh7305_usb_dc_interf[__SH7305_USB_MAX_DC_INTR];
struct usb_descriptor_endpoint __sh7305_usb_dc_endpoint[__SH7305_USB_MAX_DC_ENDP];
/* sh7305_conf_check_conf() : check and patch interface desc. */
static int sh7305_conf_check_endpoint(
struct usb_descriptor_endpoint **endpoint,
size_t *total
) {
int pipe_id;
int i;
if (endpoint == NULL)
return -3;
for (i = 0 ; endpoint[i] != NULL ; ++i)
{
if (i >= __SH7305_USB_MAX_DC_ENDP) {
usb_logger_write("- too many endpoint (%d)\n", i);
return -4;
}
*total += sizeof(struct usb_descriptor_endpoint);
pipe_id = sh7305_usb_pipe_find(endpoint[i]->bmAttributes.trans);
if (pipe_id < 0)
return pipe_id;
endpoint[i]->bEndpointAddress.number = pipe_id;
memcpy(
&__sh7305_usb_dc_endpoint[i],
endpoint[i],
sizeof(struct usb_descriptor_endpoint)
);
usb_logger_write("- use pipe %d\n", pipe_id);
}
return i;
}
/* sh7305_conf_check_conf() : check and patch interface desc. */
static int sh7305_conf_check_interface(
struct usb_full_interface **interface,
size_t *total
) {
int nbendpoint;
int i;
if (interface == NULL)
return -3;
for (i = 0 ; interface[i] != NULL ; ++i)
{
if (i >= __SH7305_USB_MAX_DC_INTR) {
usb_logger_write("- too many interface (%d)\n", i);
return -4;
}
//FIXME : check strings
*total += sizeof(struct usb_descriptor_interface);
nbendpoint = sh7305_conf_check_endpoint(interface[i]->endpoint, total);
if (nbendpoint < 0)
return nbendpoint;
interface[i]->descriptor->bInterfaceNumber = i + 1;
interface[i]->descriptor->bNumEndpoints = nbendpoint;
memcpy(
&__sh7305_usb_dc_interf[i],
interface[i],
sizeof(struct usb_descriptor_interface)
);
usb_logger_write("- use interface %d\n", i + 1);
}
return i;
}
/* sh7305_conf_check_conf() : check and patch configuration desc. */
static int sh7305_conf_check_conf(struct usb_full_config **config)
{
int nbinterf;
size_t total;
int i;
if (config == NULL)
return -2;
for (i = 0 ; config[i] != NULL ; ++i)
{
if (i >= __SH7305_USB_MAX_DC_CONF) {
usb_logger_write("- too many configuration (%d)\n", i);
return -4;
}
//FIXME : check strings
total = sizeof(struct usb_descriptor_configuration);
nbinterf = sh7305_conf_check_interface(config[i]->interface, &total);
if (nbinterf < 0)
return nbinterf;
config[i]->descriptor->wTotalLengh = total;
config[i]->descriptor->bNumInterfaces = nbinterf;
config[i]->descriptor->bConfigurationValue = i + 1;
memcpy(
&__sh7305_usb_dc_conf[i],
config[i],
sizeof(struct usb_descriptor_configuration)
);
usb_logger_write("- use configuration %d\n", i + 1);
}
return i;
}
//---
// Public API
//---
/* sh7305_usb_configuration_resolve() : check and resolve USB configuration */
int sh7305_usb_configuration_resolve(struct usb_full_device *device)
{
int nbconf;
if (device == NULL)
return -1;
//FIXME : check string validity
cpu_atomic_start();
/* patch configuration descriptors */
nbconf = sh7305_conf_check_conf(device->config);
if (nbconf < 0)
return nbconf;
/* patch device descriptor */
device->descriptor->bNumConfigurations = nbconf;
memcpy(
&__sh7305_usb_dc_device,
device->descriptor,
sizeof(struct usb_descriptor_device)
);
cpu_atomic_end();
return 0;
}

View File

@ -3,34 +3,55 @@
/* sh7305_usb_dcp_write() : send data through DCP pipe */
int sh7305_usb_dcp_write(void *buffer, size_t n)
{
//FIXME : common interface with other pipe
//FIXME : check buffer size (block send)
//
/* force kevin */
SH7305_USB_INTSTS0_CLEAR(VALID);
/* setup to write mode */
SH7305_USB.CFIFOSEL.ISEL = 1;
SH7305_USB.CFIFOSEL.CURPIPE = 0;
SH7305_USB.CFIFOSEL.BIGEND = 1;
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL == 0);
SH7305_USB_REG_SYNC(SH7305_USB.DCPCTR.BSTS == 0);
/* send data */
SH7305_USB.DCPCTR.PID = 1;
for (size_t i = 0; i < n; ++i) {
*((volatile uint8_t*)&SH7305_USB.CFIFO) = ((uint8_t*)buffer)[i];
}
/* commit transfert */
SH7305_USB.CFIFOCTR.BVAL = 1;
SH7305_USB.DCPCTR.CCPL = 1;
usb_logger_write(
"DCPCTR=%04X-CFIFOSEL=%04X-INTSTS=%04X\n"
"buffer = %d\n",
SH7305_USB.DCPCTR.word, SH7305_USB.CFIFOSEL.word, SH7305_USB.INTSTS0.word,
n);
return n;
}
/* sh7305_usb_dcp_prepare() : prepare FIFO buffer */
void sh7305_usb_dcp_prepare(void)
{
/* Configure Control FIFO pipe.
* @config
* - RCNT =1 the CFIFOCTR.DTLN is decremented only during reading
* - REW =0 buffer pointer is not rewound
* - MBW =0b00 select 8bits access
* - BIGEND =1 use big endian
* - ISEL =1 select writting pipe
* - CURPIPE =0b0000 select DCP pipe
* @notes
* - as the SH7724 documentation explain at section 31.4.8, we cannot
* change the bits access during reading or writing once setuped. So, we
* use 8-bits writing to avoid buffer alignement fault during
* configuration transaction. */
SH7305_USB.CFIFOSEL.RCNT = 1;
SH7305_USB.CFIFOSEL.REW = 0;
SH7305_USB.CFIFOSEL.MBW = 0b00;
SH7305_USB.CFIFOSEL.BIGEND = 1;
SH7305_USB.CFIFOSEL.CURPIPE = 0b0000;
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.CURPIPE != 0b0000);
SH7305_USB.CFIFOSEL.ISEL = 1;
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL == 0);
/* wait until the CDP buffer is available */
SH7305_USB_REG_SYNC(SH7305_USB.DCPCTR.BSTS == 0);
/* send data */
SH7305_USB.DCPCTR.PID = 1;
}
/* sh7305_usb_dcp_commit() : send data */
void sh7305_usb_dcp_commit(void)
{
/* wait buffer sync. and indicate that the writing has beens finished /
* @notes
* - SH7724 section 31.4.8 */
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOCTR.FRDY == 0);
SH7305_USB.CFIFOCTR.BVAL = 1;
/* finish the control transfert stage
* @notes
* - SH7724 section 31.4.29 */
SH7305_USB.DCPCTR.CCPL = 1;
}

View File

@ -1,5 +1,6 @@
#include <vhex/driver/mpu/sh/sh7305/usb.h>
#include <vhex/driver/mpu/sh/sh7305/intc.h>
#include <vhex/usb/configuration.h>
#include <vhex/usb.h>
//---
@ -15,7 +16,7 @@ int sh7305_usb_open(struct usb_full_device *device)
/* check and update device configuration */
usb_logger_write("Configuration check...\n");
ret = sh7305_usb_configuration_resolve(device);
ret = usb_config_resolve(device);
if (ret != 0)
return ret;
@ -62,23 +63,6 @@ int sh7305_usb_open(struct usb_full_device *device)
SH7305_USB.SOFCFG.BRDYM = 0;
SH7305_USB.SOFCFG.HIGH = 1;
/* Configure Control FIFO pipe.
* @notes
* - RCNT =1 the CFIFOCTR.DTLN is decremented only during reading
* - REW =0 buffer pointer is not rewound
* - MBW =0b00 select 8bits access
* - BIGEND =1 use big endian
* - ISEL =0 select reading pipe
* - CURPIPE =0b0000 select DCP pipe */
SH7305_USB.CFIFOSEL.RCNT = 1;
SH7305_USB.CFIFOSEL.REW = 0;
SH7305_USB.CFIFOSEL.MBW = 0b00;
SH7305_USB.CFIFOSEL.BIGEND = 1;
SH7305_USB.CFIFOSEL.CURPIPE = 0b0000;
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.CURPIPE != 0b0000);
SH7305_USB.CFIFOSEL.ISEL = 0;
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL != 0);
/* Pipes configuration */
usb_logger_write("USB pipes configuration...\n");
@ -98,8 +82,8 @@ int sh7305_usb_open(struct usb_full_device *device)
* - VBSE =1 enable VBUS interruption
* - RSME =0 disable Resume interruption
* - SOFE =0 disable Frame Number Update interruption
* - DVSE =0 enable Device State Transition
* - CTRE =0 disable Control Transfert Stage Transition
* - DVSE =1 enable Device State Transition
* - CTRE =1 enable Control Transfert Stage Transition
* - BEMPE =0 disable Buffer Empty interrupt
* - NRDYE =0 disable Buffer Not Ready interrupt
* - BRDYE =0 disable Buffer Ready interrupt */

View File

@ -1,4 +1,5 @@
#include <vhex/driver/mpu/sh/sh7305/usb.h>
#include <vhex/usb/configuration.h>
#include <vhex/usb/utils.h>
#include <vhex/display.h>
#include <vhex/usb.h>
@ -9,12 +10,6 @@
// Internal error API
//---
/* defined in <configuration.c> */
extern struct usb_descriptor_device __sh7305_usb_dc_device;
extern struct usb_descriptor_configuration *__sh7305_usb_dc_conf;
extern struct usb_descriptor_interface *__sh7305_usb_dc_interf;
extern struct usb_descriptor_endpoint *__sh7305_usb_dc_endpoint;
/* sh7305_usb_request_unimplemented() : not implemented request */
static void sh7305_usb_request_unimplemented(
char const * const name,
@ -42,8 +37,19 @@ static void sh7305_usb_request_error(char const * const text, ...)
}
/* sh7305_usb_request_get_descriptor() : send descriptor through DCP */
static void sh7305_usb_request_get_descriptor(int wValue, int wIndex, int wLength)
{
static void sh7305_usb_request_get_descriptor(
int wValue,
int wIndex,
size_t wLength
) {
usb_dc_device_t *dc_device;
usb_dc_config_t *dc_config;
usb_dc_interf_t *dc_interf;
usb_dc_endpnt_t *dc_endpnt;
int isidx;
int ieidx;
int esidx;
int eeidx;
int type;
int indx;
@ -54,19 +60,60 @@ static void sh7305_usb_request_get_descriptor(int wValue, int wIndex, int wLengt
type = (wValue & 0xff00) >> 8;
indx = (wValue & 0x00ff) >> 0;
/* handle request description type */
/* Return the DEVICE descriptor
* @notes
* - This is the first request, we only need to return the device
* descriptor. */
if (type == USB_REQ_DESCT_DEVICE) {
usb_logger_write("DCP write DEVICE_DESC\n");
sh7305_usb_dcp_write(
&__sh7305_usb_dc_device,
sizeof(struct usb_descriptor_device)
);
usb_logger_write("DCP write DEVICE_DESC (%04X)\n", wValue);
if (usb_config_get_dc_device(&dc_device, indx) != 0) {
sh7305_usb_request_error("unable to find the device descriptor\n");
//FIXME : handle error
}
sh7305_usb_dcp_prepare();
sh7305_usb_dcp_write(dc_device, sizeof(usb_dc_device_t));
sh7305_usb_dcp_commit();
return;
}
if (type == USB_REQ_DESCT_CONFIG) {
sh7305_usb_request_unimplemented("GET_DESC_CONF", indx, 0, 0);
/* Return the CONFIGURATION descriptor
* @notes
* - this request is performed 2 times : on the first request, we should
* return only the descriptor. On the second request, wLengh is set to
* the .wTotalLengh and we should return the current configuration
* descriptor and all of its interfaces / endpoints descriptors */
if (type == USB_REQ_DESCT_CONFIG)
{
usb_logger_write("DCP write CONFIG_DESC (%d,%d)\n", indx, wLength);
if (usb_config_get_dc_config(&dc_config, indx, &isidx, &ieidx) != 0) {
sh7305_usb_request_error("- config %d not found\n", indx);
//FIXME : handle error
}
sh7305_usb_dcp_prepare();
sh7305_usb_dcp_write(dc_config, sizeof(usb_dc_config_t));
if (wLength <= sizeof(usb_dc_config_t)) {
sh7305_usb_dcp_commit();
return;
}
for (int i = isidx ; i < ieidx ; i++) {
if (usb_config_get_dc_interf(&dc_interf, i, &esidx, &eeidx) != 0) {
sh7305_usb_request_error("- interface %d not found\n", i);
//FIXME : handle error
}
sh7305_usb_dcp_write(dc_interf, sizeof(usb_dc_interf_t));
for (int j = esidx ; j < eeidx ; ++j) {
if (usb_config_get_dc_endpnt(&dc_endpnt, j) != 0) {
sh7305_usb_request_error("- endpoint %d not found\n", j);
//FIXME : handle error
}
sh7305_usb_dcp_write(dc_endpnt, sizeof(usb_dc_endpnt_t));
}
}
sh7305_usb_dcp_commit();
return;
}
/* TODO : support all other request */
if (type == USB_REQ_DESCT_STRING) {
sh7305_usb_request_unimplemented("GET_DESC_STR", indx, 0, 0);
return;
@ -124,6 +171,8 @@ void sh7305_usb_request_handle(void)
wIndex = SH7305_USB.USBINDX.word;
wLength = SH7305_USB.USBLENG.word;
usb_logger_write("wLength = %d\n", SH7305_USB.USBLENG.word);
/* clear VALID bits */
SH7305_USB_INTSTS0_CLEAR(VALID);
@ -174,9 +223,11 @@ void sh7305_usb_request_handle(void)
return;
}
if (bRequest == SH7305_USB_REQT_SET_CONFIGURATION) {
sh7305_usb_request_unimplemented(
"SET_CONFIGURATION", wValue, wIndex, wLength
);
usb_logger_write("SET_CONFIGURATION<%d>", wIndex);
sh7305_usb_dcp_prepare();
usb_config_select_config(wIndex);
//FIXME : proper DCP FIFO config and handle config selection error
sh7305_usb_dcp_commit();
return;
}
usb_logger_write("request: unable to resolve bRequest %d\n", bRequest);

View File

@ -2,6 +2,7 @@
#include <vhex/driver/mpu/sh/sh7305/cpg.h>
#include <vhex/driver/mpu/sh/sh7305/tmu.h>
#include <vhex/driver/mpu/sh/sh7305/power.h>
#include <vhex/usb/interface.h>
#include <vhex/driver.h>
//----
@ -90,9 +91,13 @@ struct vhex_driver drv_usb = {
.configure = NULL,
.state_size = 4,
.flags = {
.USB = 1,
.SHARED = 0,
.UNUSED = 1,
.USB = 1,
.SHARED = 0,
.UNUSED = 1,
},
.module_data = &(struct usb_drv_interface){
.open = &sh7305_usb_open,
.pipe_find = &sh7305_usb_pipe_find
}
};
VHEX_DECLARE_DRIVER(06, drv_usb);

View File

@ -34,7 +34,7 @@ struct {
VCONSTRUCTOR static void __dtext_constructor(void)
{
dtext_info.pool.number = 16;
dtext_info.pool.number = 32;
dtext_info.pool.idx = -1;
dtext_info.pool.text = calloc(
dtext_info.pool.number,

View File

@ -20,8 +20,11 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in)
cpu_atomic_start();
dtable = vhex_driver_table();
for (int i = 0; i < vhex_driver_count(); ++i) {
if (dtable[i].hpowered != NULL
&& dtable[i].hpowered() == false) {
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false) {
wout->driver[i].flags.UNUSED = 1;
continue;
}
if (dtable[i].hsave == NULL) {
wout->driver[i].flags.UNUSED = 1;
continue;
}
@ -37,15 +40,15 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in)
}
//FIXME : check shared driver
if (win->driver[i].flags.UNUSED == 1) {
if (dtable[i].hpowered() == true)
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == true)
dtable[i].hpoweroff();
continue;
}
//FIXME : check if the driver is unused
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false)
dtable[i].hpoweron();
dtable[i].hrestore(win->driver[i].context);
if (dtable[i].hrestore != NULL)
dtable[i].hrestore(win->driver[i].context);
}
win->status.INIT = 1;
win->status.ACTIVE = 1;

View File

@ -0,0 +1,286 @@
#include <vhex/usb/configuration.h>
#include <vhex/usb/descriptor.h>
#include <vhex/driver/cpu.h>
#include <vhex/usb/utils.h>
#include <vhex/usb/pipe.h>
#include <vhex/usb.h>
#include <string.h>
//---
// Internals
// @TODO
// - strict descriptor check
// - proper return code error
// - check if the USB connection is already setup
// - configuration selector (SET_CONFIGURATION)
//---
/* internal copy of each descriptor */
static usb_dc_device_t usb_dc_device;
static usb_dc_config_t usb_dc_config[__USB_MAX_DC_CONF];
static usb_dc_interf_t usb_dc_interf[__USB_MAX_DC_INTR];
static usb_dc_endpnt_t usb_dc_endpnt[__USB_MAX_DC_ENDP];
/* internals descriptor counter (used in request interrupt handler) */
static int usb_dc_device_nb = 0;
static int usb_dc_config_nb = 0;
static int usb_dc_interf_nb = 0;
static int usb_dc_endpnt_nb = 0;
/* usb_conf_check_conf() : check and patch interface desc. */
static int usb_conf_check_endpoint(usb_dc_endpnt_t **endpoint, size_t *total)
{
int pipe_id;
int i;
if (endpoint == NULL)
return -3;
for (i = 0 ; endpoint[i] != NULL ; ++i)
{
if (i >= __USB_MAX_DC_ENDP) {
usb_logger_write("- too many endpoint (%d)\n", i);
return -4;
}
*total += sizeof(usb_dc_endpnt_t);
pipe_id = usb_pipe_find(endpoint[i]->bmAttributes.trans);
if (pipe_id < 0)
return pipe_id;
endpoint[i]->bEndpointAddress.number = pipe_id;
memcpy(
&usb_dc_endpnt[usb_dc_endpnt_nb],
endpoint[i],
sizeof(usb_dc_endpnt_t)
);
usb_logger_write("- use pipe %d\n", pipe_id);
usb_dc_endpnt_nb += 1;
}
return i;
}
/* usb_conf_check_conf() : check and patch interface desc. */
static int usb_conf_check_interface(
struct usb_full_interface **interface,
size_t *total
) {
int nbendpoint;
int i;
if (interface == NULL)
return -3;
for (i = 0 ; interface[i] != NULL ; ++i)
{
if (i >= __USB_MAX_DC_INTR) {
usb_logger_write("- too many interface (%d)\n", i);
return -4;
}
//FIXME : check strings
*total += sizeof(usb_dc_interf_t);
nbendpoint = usb_conf_check_endpoint(interface[i]->endpoint, total);
if (nbendpoint < 0)
return nbendpoint;
interface[i]->descriptor->bInterfaceNumber = i;
interface[i]->descriptor->bNumEndpoints = nbendpoint;
memcpy(
&usb_dc_interf[usb_dc_interf_nb],
interface[i]->descriptor,
sizeof(usb_dc_interf_t)
);
usb_logger_write("- use interface %d\n", usb_dc_interf_nb);
usb_dc_interf_nb += 1;
}
return i;
}
/* usb_conf_check_conf() : check and patch configuration desc. */
static int usb_conf_check_conf(struct usb_full_config **config)
{
int nbinterf;
size_t total;
int i;
if (config == NULL)
return -2;
for (i = 0 ; config[i] != NULL ; ++i)
{
if (i >= __USB_MAX_DC_CONF) {
usb_logger_write("- too many configuration (%d)\n", i);
return -4;
}
//FIXME : check strings
total = sizeof(struct usb_descriptor_configuration);
nbinterf = usb_conf_check_interface(config[i]->interface, &total);
if (nbinterf < 0)
return nbinterf;
config[i]->descriptor->wTotalLengh = USB_WORD_TO(total);
config[i]->descriptor->bConfigurationValue = i;
config[i]->descriptor->bNumInterfaces = nbinterf;
memcpy(
&usb_dc_config[usb_dc_config_nb],
config[i]->descriptor,
sizeof(usb_dc_config_t)
);
usb_logger_write(
"- use configuration %d with %d interface\n",
usb_dc_config_nb,
nbinterf
);
usb_dc_config_nb += 1;
}
return i;
}
//---
// Public API
//---
/* usb_config_resolve() : check and resolve USB configuration */
int usb_config_resolve(struct usb_full_device *device)
{
int nbconf;
if (device == NULL)
return -1;
//FIXME : check if the USB connection is already set
//FIXME : check string validity
cpu_atomic_start();
/* USB descriptor counter reset */
usb_dc_device_nb = 1;
usb_dc_config_nb = 0;
usb_dc_interf_nb = 0;
usb_dc_endpnt_nb = 0;
/* patch configuration descriptors */
nbconf = usb_conf_check_conf(device->config);
if (nbconf < 0)
return nbconf;
/* patch device descriptor */
device->descriptor->bNumConfigurations = nbconf;
memcpy(&usb_dc_device, device->descriptor, sizeof(usb_dc_device_t));
cpu_atomic_end();
return 0;
}
/* usb_config_select_config() : try to selecte a configuration */
int usb_config_select_config(int idx)
{
int ret;
if (idx < 0)
return -1;
cpu_atomic_start();
ret = (idx < usb_dc_config_nb) ? 0 : -2;
//TODO : real configuration selection
cpu_atomic_end();
return ret;
}
/* usb_config_get_dc_device() : get device descriptor */
int usb_config_get_dc_device(usb_dc_device_t **dc_device, int idx)
{
if (dc_device == NULL)
return -1;
if (idx != 0) {
*dc_device = NULL;
return -2;
}
*dc_device = &usb_dc_device;
return 0;
}
/* usb_config_get_dc_config() : get config descriptor */
int usb_config_get_dc_config(
usb_dc_config_t **dc_config,
int idx,
int *isidx,
int *ieidx
) {
int ret;
int start;
int end;
if (dc_config == NULL)
return -1;
if (idx < 0)
return -2;
cpu_atomic_start();
ret = -3;
*dc_config = NULL;
if (idx < usb_dc_config_nb) {
start = 0;
for (int i = 0 ; i < idx ; ++i) {
start += usb_dc_config[i].bNumInterfaces;
}
end = start + usb_dc_config[idx].bNumInterfaces;
*dc_config = &usb_dc_config[idx];
if (isidx != NULL) *isidx = start;
if (ieidx != NULL) *ieidx = end;
ret = 0;
}
cpu_atomic_end();
return ret;
}
/* usb_config_get_dc_interf() : get interface descriptor */
int usb_config_get_dc_interf(
usb_dc_interf_t **dc_interf,
int idx,
int *esidx,
int *eeidx
) {
int ret;
int start;
int end;
if (dc_interf == NULL)
return -1;
if (idx < 0)
return -2;
cpu_atomic_start();
ret = -3;
*dc_interf = NULL;
if (idx < usb_dc_interf_nb) {
start = 0;
for (int i = 0 ; i < idx ; ++i) {
start += usb_dc_interf[i].bNumEndpoints;
}
end = start + usb_dc_interf[idx].bNumEndpoints;
*dc_interf = &usb_dc_interf[idx];
if (esidx != NULL) *esidx = start;
if (eeidx != NULL) *eeidx = end;
ret = 0;
}
cpu_atomic_end();
return ret;
}
/* usb_config_get_dc_endpoint() : get endpoint descriptor */
int usb_config_get_dc_endpnt(usb_dc_endpnt_t **dc_endpnt, int idx)
{
int ret;
if (dc_endpnt == NULL)
return -1;
cpu_atomic_start();
ret = -2;
*dc_endpnt = NULL;
if (idx < usb_dc_endpnt_nb) {
*dc_endpnt = &usb_dc_endpnt[idx];
ret = 0;
}
cpu_atomic_end();
return ret;
}

View File

@ -1,12 +1,11 @@
#include <string.h>
#include <vhex/usb/info.h>
#include <vhex/usb.h>
#include <vhex/driver/cpu.h>
/* TODO : isolate */
#include <string.h>
extern bool usb_logger_attached;
extern usb_logger_t usb_logger;
/* internal module information */
extern struct usb_mod_info usb_mod_info;
//---
// Public API
@ -15,7 +14,7 @@ extern usb_logger_t usb_logger;
/* usb_logger_set() : return true if a logger is attached */
bool usb_logger_is_attached(void)
{
return usb_logger_attached;
return usb_mod_info.logger.attached;
}
/* usb_logger_set() : attach a logger to the kernel USB driver (clear) */
@ -28,14 +27,14 @@ int usb_logger_attach(usb_logger_t *logger, size_t buffer_size)
cpu_atomic_start();
ret = -2;
if (usb_logger_attached == false) {
if (usb_mod_info.logger.attached == false) {
ret = -3;
if (logger->primitive.init != NULL)
ret = logger->primitive.init(logger, buffer_size);
}
if (ret == 0) {
memcpy(&usb_logger, logger, sizeof(usb_logger_t));
usb_logger_attached = true;
memcpy(&usb_mod_info.logger.device, logger, sizeof(usb_logger_t));
usb_mod_info.logger.attached = true;
}
cpu_atomic_end();
@ -49,10 +48,13 @@ int usb_logger_clear(void)
cpu_atomic_start();
ret = -1;
if (usb_logger_attached == true) {
if (usb_mod_info.logger.attached == true) {
ret = -2;
if (usb_logger.primitive.clear != NULL)
ret = usb_logger.primitive.clear(&usb_logger);
if (usb_mod_info.logger.device.primitive.clear != NULL) {
ret = usb_mod_info.logger.device.primitive.clear(
&usb_mod_info.logger.device
);
}
}
cpu_atomic_end();
@ -69,10 +71,14 @@ ssize_t usb_logger_write(char *format, ...)
cpu_atomic_start();
ret = -1;
if (usb_logger_attached == true) {
if (usb_mod_info.logger.attached == true) {
ret = -2;
if (usb_logger.primitive.write != NULL)
ret = usb_logger.primitive.write(&usb_logger, format, ap);
if (usb_mod_info.logger.device.primitive.write != NULL)
ret = usb_mod_info.logger.device.primitive.write(
&usb_mod_info.logger.device,
format,
ap
);
}
cpu_atomic_end();
@ -88,10 +94,14 @@ ssize_t usb_logger_getline(char **lineptr, size_t *n)
cpu_atomic_start();
ret = -1;
if (usb_logger_attached == true) {
if (usb_mod_info.logger.attached == true) {
ret = -2;
if (usb_logger.primitive.getline != NULL)
ret = usb_logger.primitive.getline(&usb_logger, lineptr, n);
if (usb_mod_info.logger.device.primitive.getline != NULL)
ret = usb_mod_info.logger.device.primitive.getline(
&usb_mod_info.logger.device,
lineptr,
n
);
}
cpu_atomic_end();
@ -105,14 +115,16 @@ int usb_logger_detach(void)
cpu_atomic_start();
ret = -1;
if (usb_logger_attached == true) {
if (usb_mod_info.logger.attached == true) {
ret = -2;
if (usb_logger.primitive.quit != NULL)
ret = usb_logger.primitive.quit(&usb_logger);
if (usb_mod_info.logger.device.primitive.quit != NULL)
ret = usb_mod_info.logger.device.primitive.quit(
&usb_mod_info.logger.device
);
}
if (ret == 0) {
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
usb_logger_attached = false;
memset(&usb_mod_info.logger.device, 0x00, sizeof(usb_logger_t));
usb_mod_info.logger.attached = false;
}
cpu_atomic_end();

View File

@ -0,0 +1,17 @@
#include <vhex/usb/info.h>
#include <vhex/usb.h>
/* internal module information */
extern struct usb_mod_info usb_mod_info;
//---
// Public API
//---
/* usb_pipe_find() : find a pipe of type `type` */
int usb_pipe_find(int type)
{
if (usb_mod_info.driver.pipe_find != NULL)
return usb_mod_info.driver.pipe_find(type);
return -1;
}

View File

@ -0,0 +1,17 @@
#include <vhex/usb/info.h>
#include <vhex/usb.h>
/* internal module information */
extern struct usb_mod_info usb_mod_info;
//---
// Public API
//---
/* usb_open() : open primitive */
int usb_open(struct usb_full_device *device)
{
if (usb_mod_info.driver.open != NULL)
return usb_mod_info.driver.open(device);
return -1;
}

View File

@ -1,29 +1,42 @@
#include <string.h>
#include <vhex/usb.h>
#include <vhex/driver.h>
#include <vhex/module.h>
#include <vhex/usb/interface.h>
#include <vhex/usb/info.h>
#include <vhex/usb.h>
#include <string.h>
//---
// Kernel module information
//---
/* Internal USB driver information */
bool usb_logger_attached;
usb_logger_t usb_logger;
/* internal USB driver information */
struct usb_mod_info usb_mod_info;
/* __timer_init() : initialize the timer module */
/* __usb_init() : initialize the usb module */
static void __usb_init(void)
{
usb_logger_attached = false;
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
struct vhex_driver *driver;
memset(&usb_mod_info, 0x00, sizeof(usb_mod_info));
driver = vhex_driver_table();
for (int i = 0; i < vhex_driver_count(); ++i) {
if (driver[i].flags.USB) {
memcpy(
&usb_mod_info.driver,
driver[i].module_data,
sizeof(struct usb_drv_interface)
);
break;
}
}
}
/* __timer_quit() : uninitialize the timer module */
/* __usb_quit() : uninitialize the usb module */
static void __usb_quit(void)
{
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
usb_logger_attached = false;
memset(&usb_mod_info, 0x00, sizeof(usb_mod_info));
}
/* declare the timer module */
@ -32,5 +45,6 @@ struct vhex_module mod_usb = {
.name = "USB",
.init = &__usb_init,
.quit = &__usb_quit,
};
VHEX_DECLARE_MODULE(06, mod_usb);

2
vxdev
View File

@ -1,3 +1,3 @@
#!/usr/bin/env bash
python3 scripts/vxdev $@
/usr/bin/env python3 scripts/vxdev $@

View File

@ -9,7 +9,7 @@ target = [
[build]
configure = './vxdev configure'
build = './vxdev build'
build = './vxdev build --verbose'
install = './vxdev install'
uninstall = './vxdev uninstall'
@ -31,7 +31,8 @@ assets_prefix = [
'-mb',
'-m4-nofpu',
'-fstrict-volatile-bitfields',
'-Wa,--dsp'
'-Wa,--dsp',
'-fstack-protector-all',
]
VXSDK_PUBLIC_BUILD_LIBS = [
'@COMMON@',
@ -40,7 +41,8 @@ assets_prefix = [
'-Wl,--no-whole-archive',
'@sh-elf-vhex@',
'-lc',
'-lgcc'
'-lgcc',
'-lssp_nonshared',
]
VXSDK_PUBLIC_BUILD_LDFLAGS = [
'-T {VXSDK_CURRENT_SOURCE_DIR}/boards/fxcg50/fxcg50.ld',