Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
23 changes: 23 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,24 @@ config RX
help
Renesas RX architecture

config DSPIC
bool
select ARCH_IS_SET
select STACK_GROWS_UP
select LITTLE_ENDIAN
select ARCH_HAS_THREAD_LOCAL_STORAGE
select TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE
select THREAD_LOCAL_STORAGE
select INIT_STACKS
select STACK_SENTINAL
select ATOMIC_OPERATIONS_C
select ARCH_HAS_VECTOR_TABLE_RELOCATION
select CPU_HAS_ICACHE
select CACHE_MANAGEMENT
select TICKLESS_CAPABLE
help
dspic architecture

config ARCH_IS_SET
bool
help
Expand Down Expand Up @@ -376,6 +394,11 @@ config STACK_GROWS_UP
Select this option if the architecture has upward growing thread
stacks. This is not common.

config STACK_SENTINAL
bool
help
It is a debugging and safety feature at the boundaries of the stack.

config NO_UNUSED_STACK_INSPECTION
bool
help
Expand Down
3 changes: 3 additions & 0 deletions arch/archs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ archs:
- name: rx
path: rx
full_name: Renesas RX
- name: dspic
path: dspic
full_name: Microchip dsPIC
8 changes: 8 additions & 0 deletions arch/dspic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
if(CONFIG_BIG_ENDIAN)
set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-big)
else()
set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-little)
endif()
zephyr_include_directories(${XCDSC_TOOLCHAIN_PATH}/support/generic/h/)
zephyr_include_directories(include)
add_subdirectory(core)
23 changes: 23 additions & 0 deletions arch/dspic/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) 2025, Microchip Technology Inc.
# SPDX-License-Identifier: Apache-2.0

menu "DSPIC Options"
depends on DSPIC

config ARCH
string
default "dspic"

config GEN_ISR_TABLES
default y

config DYNAMIC_INTERRUPTS
default n

config NUM_IRQS
default 279

config GEN_IRQ_START_VECTOR
default 0

endmenu
18 changes: 18 additions & 0 deletions arch/dspic/core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
zephyr_library()

zephyr_library_sources(
cpu_idle.c
fatal.c
irq_manage.c
isr_wrapper.c
prep_c.c
thread.c
swap.c
tls.c
reset0.S
init.S
vector_table.S
reset1.S
)

zephyr_linker_sources(ROM_START SORT_KEY 0x00 vector_table.ld)
34 changes: 34 additions & 0 deletions arch/dspic/core/cpu_idle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2025, Microchip Technology Inc.
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/irq.h>
#include <zephyr/tracing/tracing.h>
#include <zephyr/arch/cpu.h>
#include <xc.h>

#ifndef CONFIG_ARCH_HAS_CUSTOM_CPU_IDLE
void arch_cpu_idle(void)
{
__builtin_disable_interrupts();
Idle();
__builtin_enable_interrupts();
}
#endif

#ifndef CONFIG_ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE
void arch_cpu_atomic_idle(unsigned int key)
{
__builtin_disable_interrupts();
Idle();
arch_irq_unlock(key);
__builtin_enable_interrupts();
}
#endif

FUNC_NORETURN void arch_system_halt(unsigned int reason)
{
(void)reason;
CODE_UNREACHABLE;
}
123 changes: 123 additions & 0 deletions arch/dspic/core/fatal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2025, Microchip Technology Inc.
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

#ifndef _ASMLANGUAGE
#include <xc.h>
#ifdef __cplusplus
extern "C" {
#endif

LOG_MODULE_REGISTER(dspic, 4);

volatile uint32_t reason, address;

#define EXCEPTION_HANDLER __attribute__((interrupt, no_auto_psv, weak))
#define BUS_ERROR_MASK 0xF
#define MATH_ERROR_MASK 0x1F
#define GENERAL_TRAP_MASK 0x8000000Fu

void __attribute__((weak)) TRAPS_halt_on_error(void);

Check warning on line 24 in arch/dspic/core/fatal.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

FUNCTION_ARGUMENTS

arch/dspic/core/fatal.c:24 function definition argument 'void' should also have an identifier name
void EXCEPTION_HANDLER _BusErrorTrap(void);
void EXCEPTION_HANDLER _AddressErrorTrap(void);
void EXCEPTION_HANDLER _IllegalInstructionTrap(void);
void EXCEPTION_HANDLER _MathErrorTrap(void);
void EXCEPTION_HANDLER _StackErrorTrap(void);
void EXCEPTION_HANDLER _GeneralTrap(void);
void EXCEPTION_HANDLER _ReservedTrap0(void);
void EXCEPTION_HANDLER _ReservedTrap7(void);

void EXCEPTION_HANDLER _ReservedTrap0(void)
{
}
void EXCEPTION_HANDLER _ReservedTrap7(void)
{
}

void __attribute__((weak)) TRAPS_halt_on_error(void)
{
/* stay here forever */
while (1) {
}
}

/** Bus error.**/
void EXCEPTION_HANDLER _BusErrorTrap(void)
{
/* Identify bus error via INTCON3, fetch trap address from
* PCTRAP, and reset error flags
*/
reason = INTCON3 & BUS_ERROR_MASK;
address = PCTRAP;
LOG_ERR("ERROR !!! Exception reason = %d, address = 0x%x\n", reason, address);
INTCON3 &= ~(BUS_ERROR_MASK);
PCTRAP = 0;
TRAPS_halt_on_error();
}

/** Address error.**/
void EXCEPTION_HANDLER _AddressErrorTrap(void)
{
/* fetch trap address from PCTRAP
* and reset error flags
*/
address = PCTRAP;
LOG_ERR("ERROR !!! Exception reason = %s, address = 0x%x\n", "Address Error", address);
INTCON1bits.ADDRERR = 0;
PCTRAP = 0;
TRAPS_halt_on_error();
}

/** Illegal instruction.**/
void EXCEPTION_HANDLER _IllegalInstructionTrap(void)
{
address = PCTRAP;
LOG_ERR("ERROR !!! Exception reason = %s, address = 0x%x\n", "Illegal Instruction",
address);
INTCON1bits.BADOPERR = 0;
Copy link
Collaborator

@harishagari harishagari Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for using different approaches in different fucntions for clearing the trap (using mask or writing to 0 to the bitfield)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came from different developers, we will unify the approaches.
failed to catch this in the review

PCTRAP = 0;
TRAPS_halt_on_error();
}

/** Math error.**/
void EXCEPTION_HANDLER _MathErrorTrap(void)
{
/* Identify math error via INTCON4, fetch trap address from
* PCTRAP, and reset error flags
*/
reason = INTCON4 & MATH_ERROR_MASK;
address = PCTRAP;
LOG_ERR("ERROR !!! Exception reason = %d, address = 0x%x\n", reason, address);
INTCON4 &= ~(MATH_ERROR_MASK);
PCTRAP = 0;
TRAPS_halt_on_error();
}

/** Stack error.**/
void EXCEPTION_HANDLER _StackErrorTrap(void)
{
INTCON1bits.STKERR = 0;
PCTRAP = 0;
TRAPS_halt_on_error();
}

/** Generic error.**/
void EXCEPTION_HANDLER _GeneralTrap(void)
{
reason = INTCON5 & GENERAL_TRAP_MASK;
address = PCTRAP;
LOG_ERR("ERROR !!! Exception reason = %d, address = 0x%x\n", reason, address);
INTCON5 &= ~(GENERAL_TRAP_MASK);
PCTRAP = 0;
TRAPS_halt_on_error();
}

#ifdef __cplusplus
}
#endif

#endif /* _ASMLANGUAGE */
62 changes: 62 additions & 0 deletions arch/dspic/core/init.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2025, Microchip Technology Inc.
* SPDX-License-Identifier: Apache-2.0
*/

.section .init,code
.global __custom_data_init
.global __custom_data_init_extended

.equ __custom_data_init, __custom_data_init_extended
__custom_data_init_extended:

.equiv FMT_CLEAR,0
.equiv FMT_COPY2,1
.equiv FMT_COPY3,2
.equiv FMT_CALL, 3
.equiv FMT_DUO_COPY3,0x1F

#define DINIT w0
#define TLSOFFSET w1
#define TBLOFFSET w9
#define DSTOFFSET w10
#define LEN w11
#define FORMAT w12

mov.l w0, TBLOFFSET
bra 4f

1:
add.l DSTOFFSET,TLSOFFSET,DSTOFFSET
mov.l [TBLOFFSET++], LEN
mov.l [TBLOFFSET++], FORMAT

cp.b FORMAT, #FMT_CALL
bra nz, 2f
call DSTOFFSET
bra 4f

2:
cp.b FORMAT, #FMT_CLEAR
bra nz, 2f
9:
sub.l LEN, #1, LEN
repeat LEN
clr.b [DSTOFFSET++]
bra 4f

2:
cp.b FORMAT, #FMT_COPY2
bra z, 3f

3:
sub.l LEN, #1, LEN
repeat LEN
mov.b [TBLOFFSET++], [DSTOFFSET++]
add.l TBLOFFSET, #3, TBLOFFSET
and1.l TBLOFFSET, #0x7C, TBLOFFSET

4:
sub.l [TBLOFFSET++], #0, DSTOFFSET
bra nz, 1b
return
67 changes: 67 additions & 0 deletions arch/dspic/core/irq_manage.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2025, Microchip Technology Inc.
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/kernel.h>
#include <kswap.h>

#ifndef _ASMLANGUAGE
#include <xc.h>

#ifdef __cplusplus
extern "C" {
#endif

void z_irq_spurious(const void *unused)
{
ARG_UNUSED(unused);
while (1) {
}
return;
}

Check warning on line 22 in arch/dspic/core/irq_manage.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

RETURN_VOID

arch/dspic/core/irq_manage.c:22 void function return statements are not generally useful

void arch_irq_enable(unsigned int irq)
{
volatile uint32_t *int_enable_reg[] = {&IEC0, &IEC1, &IEC2, &IEC3, &IEC4,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these registers can differ between dsPIC33A , dsPIC33C and other dsPIC architectures. should we have specific folders for this , instead having this part of "dsPIC" folder?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, will assess how to modify this and redesign.

&IEC5, &IEC6, &IEC7, &IEC8};

unsigned int reg_index = irq / (sizeof(uint32_t) << 3);
unsigned int bit_pos = irq % (sizeof(uint32_t) << 3);

/* Enable the interrupt by setting it's bit in interrupt enable register*/
*int_enable_reg[reg_index] |= (uint32_t)(1u << bit_pos);

return;
}

Check warning on line 36 in arch/dspic/core/irq_manage.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

RETURN_VOID

arch/dspic/core/irq_manage.c:36 void function return statements are not generally useful

int arch_irq_is_enabled(unsigned int irq)
{
volatile uint32_t *int_enable_reg[] = {&IEC0, &IEC1, &IEC2, &IEC3, &IEC4,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dsPIC33AK128MC106 has IEC0 to IEC8
dsPIC33AK512MPS512 has IEC0 to IEC11 , shouldn't we handle this in a proper way?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, will assess how to modify this and redesign.

&IEC5, &IEC6, &IEC7, &IEC8};

unsigned int reg_index = irq / (sizeof(uint32_t) << 3);
unsigned int bit_pos = irq % (sizeof(uint32_t) << 3);

return ((*int_enable_reg[reg_index] >> bit_pos) & 0x1u);
}

void arch_irq_disable(unsigned int irq)
{
volatile uint32_t *int_enable_reg[] = {&IEC0, &IEC1, &IEC2, &IEC3, &IEC4,
&IEC5, &IEC6, &IEC7, &IEC8};

unsigned int reg_index = irq / (sizeof(uint32_t) << 3);
unsigned int bit_pos = irq % (sizeof(uint32_t) << 3);

/* Disable the interrupt by clearing it's bit in interrupt enable register*/
*int_enable_reg[reg_index] &= (uint32_t)(~(1u << bit_pos));

return;
}

Check warning on line 61 in arch/dspic/core/irq_manage.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

RETURN_VOID

arch/dspic/core/irq_manage.c:61 void function return statements are not generally useful

#ifdef __cplusplus
}
#endif

#endif /* _ASMLANGUAGE */
Loading
Loading