From a64390e9d66008419e5029c2b0ffb65b090a7e47 Mon Sep 17 00:00:00 2001 From: Muhammed Zamroodh Date: Wed, 15 Oct 2025 12:20:07 +0530 Subject: [PATCH] Release: v6.0 Highlights: - HW timer for Sys timer made configurable - arch swap and isr code cleaned up - Added board documentation Fixes: - Wrong RAM size for 128k device - Busywait implementation fixed - Fix register pollution bug - Fix for Configs breaking other board builds - Other minor fixes Signed-off-by: Muhammed Zamroodh --- arch/dspic/core/CMakeLists.txt | 2 +- arch/dspic/core/isr_wrapper.S | 283 ++------------- arch/dspic/core/offsets/offsets.c | 1 + arch/dspic/core/swap.S | 84 +++++ arch/dspic/core/swap.c | 61 ---- arch/dspic/include/kernel_arch_swap.h | 340 ------------------ arch/dspic/include/kernel_arch_swap_macro.S | 316 ++++++++++++++++ .../dspic33/dspic33a_curiosity/board.yml | 1 - .../doc/img/dsPIC33AK128MC106.webp | Bin 0 -> 13000 bytes .../doc/img/dsPIC33AK512MPS512.webp | Bin 0 -> 12307 bytes .../doc/img/dsPIC33AK512MPS512.webp.license | 4 + .../dspic33a_curiosity/doc/img/ev74h48a.webp | Bin 0 -> 66802 bytes .../dspic33/dspic33a_curiosity/doc/index.rst | 207 +++++++++++ .../dspic33a_curiosity_p33ak128mc106.dts | 1 - .../dspic33a_curiosity_p33ak128mc506.dts | 1 - .../dspic33a_curiosity_p33ak512mps512.dts | 1 - cmake/compiler/xcdsc/generic.cmake | 58 +-- cmake/toolchain/xcdsc/Kconfig | 6 + drivers/gpio/Kconfig.mchp_dspic | 1 + drivers/pinctrl/pinctrl_mchp_dspic33_g1.c | 5 +- drivers/serial/Kconfig.dspic_uart | 1 + drivers/serial/uart_mchp_dspic33_g1.c | 5 +- drivers/timer/CMakeLists.txt | 1 - drivers/timer/mchp_dspic33_timer.c | 120 +++---- .../timer/microchip,dspic33-timer.yaml | 2 +- dts/dspic/p33ak128mc106.dtsi | 4 +- dts/dspic/p33ak512mps512.dtsi | 2 +- include/zephyr/toolchain/xcdsc.h | 25 +- samples/basic/blinky/prj.conf | 1 - soc/microchip/dspic33/dspic33a/Kconfig.soc | 1 - soc/microchip/dspic33/soc.yml | 1 - .../mem_protect/stack_random/testcase.yaml | 1 + tests/kernel/mem_protect/stackprot/src/main.c | 8 + 33 files changed, 777 insertions(+), 767 deletions(-) create mode 100644 arch/dspic/core/swap.S delete mode 100644 arch/dspic/core/swap.c delete mode 100644 arch/dspic/include/kernel_arch_swap.h create mode 100644 arch/dspic/include/kernel_arch_swap_macro.S create mode 100644 boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK128MC106.webp create mode 100644 boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK512MPS512.webp create mode 100644 boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK512MPS512.webp.license create mode 100644 boards/microchip/dspic33/dspic33a_curiosity/doc/img/ev74h48a.webp create mode 100644 boards/microchip/dspic33/dspic33a_curiosity/doc/index.rst delete mode 100644 boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc506.dts diff --git a/arch/dspic/core/CMakeLists.txt b/arch/dspic/core/CMakeLists.txt index 2e9dba116d1ee..cde4e1c12aa66 100644 --- a/arch/dspic/core/CMakeLists.txt +++ b/arch/dspic/core/CMakeLists.txt @@ -7,7 +7,7 @@ zephyr_library_sources( isr_wrapper.S prep_c.c thread.c - swap.c + swap.S tls.c reset0.S init.S diff --git a/arch/dspic/core/isr_wrapper.S b/arch/dspic/core/isr_wrapper.S index 0c278ec848d60..001801215bab0 100644 --- a/arch/dspic/core/isr_wrapper.S +++ b/arch/dspic/core/isr_wrapper.S @@ -4,15 +4,9 @@ */ #include #include +#include #define OFFSET DT_PROP(DT_NODELABEL(intc0), if_offset) -#if defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK512MPS512) -#define RAM_END 0x00013FFC -#elif defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK128MC106) -#define RAM_END 0x00007FFC -#endif - - .equ IF_OFFSET, OFFSET .section .text,code @@ -23,11 +17,13 @@ __COMMONInterrupt: .section .isr.text._COMMONInterrupt,keep,code,keep lnk #0x4 + /* Handle ISR calls and clear handles IRQ + */ mov.l w8, [w15++] - mov.sl #__kernel,w8 + mov.sl #__kernel + ___cpu_t_nested_OFFSET,w8 add.l [w8],#1,[w8] mov.w _INTTREGbits,w0 - and.l #(0x1ff&0xFFFF),w0 + and.l #0x1ff,w0 sub.l w0,#9,w0 mov.sl #__sw_isr_table,w1 sl.l w0,#3,w0 @@ -35,289 +31,74 @@ __COMMONInterrupt: mov.l [w2+4],w1 mov.l [w2],w0 - call w1 mov.w _INTTREGbits,w0 - and.l #(0x1ff&0xFFFF),w0 + and.l #0x1ff,w0 sub.l w0,#9,w0 call _arch_dspic_irq_clear - + /* Check and perform context switch + */ sub.l [w8],#1,w0 mov.l w0,[w8] + mov.l [--w15], w8 cp.l w0,#0 bra nz,.L2 - mov.sl #__kernel+20,w1 + mov.sl #__kernel + ___kernel_t_ready_q_OFFSET,w1 mov.l [w1],w1 - mov.sl #__kernel+8,w0 + mov.sl #__kernel + ___cpu_t_current_OFFSET,w0 mov.l [w0],w0 cp.l w1,w0 bra z,.L2 cp0.b _z_sys_post_kernel bra z,.L2 - mov.l [--w15], w8 ulnk CTXTSWP #0x0 mov.l w0, [w15++] mov.l #RAM_END, w0 mov.l w0, SPLIM - mov.l sr, w0 - and #0xe0, w0 - bra nz, 1f - mov.l [--w15], w0 - ulnk - mov.l w2, [w15++] - mov.l w1, [w15++] - mov.l w0, [w15++] - mov.l #_swap_working_set, w0 - mov.l [--w15], [w0++] - mov.l [--w15], [w0++] - mov.l [--w15], [w0] - mov.l [--w15], w1 - mov.l sr, [w15++] - mov.l w1, [w15++] - mov.l [w0--], w2 - mov.l [w0--], w1 - mov.l [w0], w0 - mov.l w0, [w15++] - 1: mov.l [--w15], w0 - push RCOUNT - push.l fsr - push.l fcr - mov.l w0, [w15++] - mov.l w1, [w15++] - mov.l w2, [w15++] - mov.l w3, [w15++] - mov.l w4, [w15++] - mov.l w5, [w15++] - mov.l w6, [w15++] - mov.l w7, [w15++] - push.l f0 - push.l f1 - push.l f2 - push.l f3 - push.l f4 - push.l f5 - push.l f6 - push.l f7 - lnk #0x4 - - mov.l #__kernel, w0 - mov.l #___cpu_t_current_OFFSET, w1 - add w0, w1, w1 - mov.l [w1], w2 - mov.l #___thread_t_callee_saved_OFFSET, w1 - add w2, w1, w1 + z_dspic_save_caller_saved + z_dspic_save_callee_saved - mov.l w8, [w1++] - mov.l w9, [w1++] - mov.l w10, [w1++] - mov.l w11, [w1++] - mov.l w12, [w1++] - mov.l w13, [w1++] - mov.l w14, [w1++] - mov.l f8, [w1++] - mov.l f9, [w1++] - mov.l f10, [w1++] - mov.l f11, [w1++] - mov.l f12, [w1++] - mov.l f13, [w1++] - mov.l f14, [w1++] - mov.l f15, [w1++] - mov.l f16, [w1++] - mov.l f17, [w1++] - mov.l f18, [w1++] - mov.l f19, [w1++] - mov.l f20, [w1++] - mov.l f21, [w1++] - mov.l f22, [w1++] - mov.l f23, [w1++] - mov.l f24, [w1++] - mov.l f25, [w1++] - mov.l f26, [w1++] - mov.l f27, [w1++] - mov.l f28, [w1++] - mov.l f29, [w1++] - mov.l f30, [w1++] - mov.l f31, [w1++] - mov.l #RCOUNT, w2 - mov.l [w2], [w1++] - mov.l #CORCON, w2 - mov.l [w2], [w1++] - mov.l #MODCON, w2 - mov.l [w2], [w1++] - mov.l #XMODSRT, w2 - mov.l [w2], [w1++] - mov.l #XMODEND, w2 - mov.l [w2], [w1++] - mov.l #YMODSRT, w2 - mov.l [w2], [w1++] - mov.l #YMODEND, w2 - mov.l [w2], [w1++] - mov.l #XBREV, w2 - mov.l [w2], [w1++] - slac.l A, [W1++] - sac.l A, [W1++] - suac.l A, [W1++] - slac.l B, [W1++] - sac.l B, [W1++] - suac.l B, [W1++] - mov.l w15, [w1++] - mov.l w14, [w1++] - mov.l #SPLIM, w2 - mov.l [w2], [w1++] + mov.l #__kernel_ready_q_cache_OFFSET, w2 + mov.l [w2], w2 + mov.l #__kernel_current_OFFSET, w1 + mov.l w2, [w1] - mov.sl #__kernel+20,w0 - mov.l [w0],w0 - mov.sl #__kernel,w1 - mov.l w0,[w1 + ___cpu_t_current_OFFSET] - mov.l [w0 + ___thread_t_tls_OFFSET],w0 - rcall __set_tls - - mov.l #__kernel, w0 - mov.l #___cpu_t_current_OFFSET, w1 - add w0, w1, w1 - mov.l [w1], w2 - mov.l #___thread_t_callee_saved_OFFSET, w1 - add w2, w1, w1 +#ifdef CONFIG_CURRENT_THREAD_USE_TLS + mov.l [w2 + ___thread_t_tls_OFFSET], w0 + rcall __set_tls +#endif - mov.l [w1++], w8 - mov.l [w1++], w9 - mov.l [w1++], w10 - mov.l [w1++], w11 - mov.l [w1++], w12 - mov.l [w1++], w13 - mov.l [w1++], w14 - mov.l [w1++], f8 - mov.l [w1++], f9 - mov.l [w1++], f10 - mov.l [w1++], f11 - mov.l [w1++], f12 - mov.l [w1++], f13 - mov.l [w1++], f14 - mov.l [w1++], f15 - mov.l [w1++], f16 - mov.l [w1++], f17 - mov.l [w1++], f18 - mov.l [w1++], f19 - mov.l [w1++], f20 - mov.l [w1++], f21 - mov.l [w1++], f22 - mov.l [w1++], f23 - mov.l [w1++], f24 - mov.l [w1++], f25 - mov.l [w1++], f26 - mov.l [w1++], f27 - mov.l [w1++], f28 - mov.l [w1++], f29 - mov.l [w1++], f30 - mov.l [w1++], f31 - mov.l #RCOUNT, w2 - mov.l [w1++], [w2] - mov.l #CORCON, w2 - mov.l [w1++], [w2] - mov.l #MODCON, w2 - mov.l [w1++], [w2] - mov.l #XMODSRT, w2 - mov.l [w1++], [w2] - mov.l #XMODEND, w2 - mov.l [w1++], [w2] - mov.l #YMODSRT, w2 - mov.l [w1++], [w2] - mov.l #YMODEND, w2 - mov.l [w1++], [w2] - mov.l #XBREV, w2 - mov.l [w1++], [w2] - clr A - clr B - llac.l [w1++], A - lac.l [w1++], A - luac.l [w1++], A - llac.l [w1++], B - lac.l [w1++], B - luac.l [w1++], B - mov.l [w1++], w15 - mov.l [w1++], w14 - mov.l #SPLIM, w2 - mov.l [w1++], [w2] + z_dspic_restore_callee_saved + z_dspic_restore_caller_saved - ulnk - pop.l f7 - pop.l f6 - pop.l f5 - pop.l f4 - pop.l f3 - pop.l f2 - pop.l f1 - pop.l f0 - mov.l [--w15], w7 - mov.l [--w15], w6 - mov.l [--w15], w5 - mov.l [--w15], w4 - mov.l [--w15], w3 - mov.l [--w15], w2 - mov.l [--w15], w1 - mov.l [--w15], w0 - pop.l fcr - pop.l fsr - pop RCOUNT - mov.l w0, [w15++] - mov.l sr, w0 - and #0xe0, w0 - mov.l [--w15], w0 - bra nz, 1f mov.l w2, [w15++] mov.l w1, [w15++] mov.l w0, [w15++] - mov.l #_swap_working_set, w0 - mov.l [--w15], [w0++] - mov.l [--w15], [w0++] - mov.l [--w15], [w0] - mov.l [--w15], w1 - mov.l [--w15], w2 - mov.l w2, sr - mov.l w1, [w15++] - mov.l [w0--], w2 - mov.l [w0--], w1 - mov.l [w0], w0 - lnk #0x4 - 1: - mov.l w2, [w15++] - mov.l w1, [w15++] - mov.l w0, [w15++] - mov.sl #__kernel, w0 - mov.l [w0 + ___cpu_t_current_OFFSET], w1 - mov.l #___thread_t_arch_OFFSET, w2 - add.l w2, w1, w1 - mov.l [w1 + ___thread_arch_t_swapped_from_thread_OFFSET], w0 + mov.sl #__kernel_current_OFFSET, w0 + mov.l [w0], w1 + mov.l [w1 + __thread_t_arch_swapped_from_thread_OFFSET], w0 mov.l #0, w2 cp.l w2, w0 mov.l [--w15], w0 - bra z, 1f - mov.l [w1 + ___thread_arch_t_swap_return_value_OFFSET], w0 - mov.l w2, [w1 + ___thread_arch_t_swapped_from_thread_OFFSET] - 1: + bra z, 2f + mov.l [w1 + __thread_t_arch_swap_return_value_OFFSET], w0 + mov.l w2, [w1 + __thread_t_arch_swapped_from_thread_OFFSET] + 2: mov.l [--w15], w1 mov.l [--w15], w2 nop retfie - - .L2: - mov.l [--w15], w8 ulnk -.L1: retfie - .section .text._arch_dspic_irq_clear,code - .align 4 - .global _arch_dspic_irq_clear ; export - .type _arch_dspic_irq_clear,@function -_arch_dspic_irq_clear: - +GTEXT(arch_dspic_irq_clear) +SECTION_FUNC(TEXT, arch_dspic_irq_clear) lnk #0 lsr.l w0,#5,w1 sl.l w1,#2,w1 diff --git a/arch/dspic/core/offsets/offsets.c b/arch/dspic/core/offsets/offsets.c index 08d68715feb95..822c9e9eb813f 100644 --- a/arch/dspic/core/offsets/offsets.c +++ b/arch/dspic/core/offsets/offsets.c @@ -7,6 +7,7 @@ #include #include +GEN_OFFSET_SYM(_thread_arch_t, cpu_level); GEN_OFFSET_SYM(_thread_arch_t, swap_return_value); GEN_OFFSET_SYM(_thread_arch_t, swapped_from_thread); diff --git a/arch/dspic/core/swap.S b/arch/dspic/core/swap.S new file mode 100644 index 0000000000000..692201f6b696f --- /dev/null +++ b/arch/dspic/core/swap.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025, Microchip Technology Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file swap.S + * + * @brief handles thread swap logic for dsPIC33A devices + */ +#include +#include +#include + + .equ NUM_TEMP_REGS, 12 + + .section .bss + .align 4 + .globl _swap_working_set +_swap_working_set: + .space NUM_TEMP_REGS*4 + +GTEXT(arch_swap) +SECTION_FUNC(TEXT, arch_swap) + + lnk #0x0 + mov.l w0, [w15++] + +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + rcall _z_thread_mark_switched_out +#endif + mov.l [--w15], w2 + + /* Get the kernel and thread structures + * w0 -> current _thread_t structure + */ + mov.l #__kernel_current_OFFSET, w0 + mov.l [w0], w1 + + mov.l w2, [w1 + __thread_t_arch_cpu_level_OFFSET] + + /*move -EAGAIN to the member (2s compliment of 11)*/ + mov.l #0xfffffff5, w2 + mov.l w2, [w1 + __thread_t_arch_swap_return_value_OFFSET] + mov.l #1, w2 + mov.l w2, [w1 + __thread_t_arch_swapped_from_thread_OFFSET] + + mov.l w1, w2 + mov.sl #__kernel_ready_q_cache_OFFSET, w0 + mov.l [w0], w1 + cp.l w1, w2 + bra z, 2f + + z_dspic_do_swap + 2: + + mov.l w1, [w15++] + mov.l w2, [w15++] + mov.l w0, [w15++] +#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING + rcall _z_thread_mark_switched_in +#endif + mov.sl #__kernel_current_OFFSET, w0 + mov.l [w0], w1 + + mov.l [w1 + __thread_t_arch_swapped_from_thread_OFFSET], w0 + cp.l w0, #0 + mov.l #0, w0 + mov.l w0, [w1 + __thread_t_arch_swapped_from_thread_OFFSET] + mov.l [--w15], w0 + bra z, 3f + + mov.l [w1 + __thread_t_arch_swap_return_value_OFFSET], w0 + 3: + mov.l [w1 + __thread_t_arch_cpu_level_OFFSET], w1 + cp.l w1, #0x0 + + bra z, 2f + bset.b 0x71, #0x7 + 2: + mov.l [--w15], w2 + mov.l [--w15], w1 + ulnk + return diff --git a/arch/dspic/core/swap.c b/arch/dspic/core/swap.c deleted file mode 100644 index 49be36e8c28b7..0000000000000 --- a/arch/dspic/core/swap.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2025, Microchip Technology Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include "kswap.h" - -int swap_working_set[NUM_TEMP_REGS]; - -int arch_swap(unsigned int key) -{ -#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING - z_thread_mark_switched_out(); -#endif - - register int result __asm__("w0"); - /* store off key and return value */ - _current->arch.cpu_level = key; - _current->arch.swap_return_value = -EAGAIN; - _current->arch.swapped_from_thread = 1; - result = _current->arch.swap_return_value; - - /*Check if swap is needed*/ - if (_kernel.ready_q.cache != _current) { - z_dspic_do_swap(); - } - -#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING - z_thread_mark_switched_in(); -#endif - - /* This arch has only one SP and dosent use any kernel call style ABI - * Which means a return will pollute the next stacks working reg (w0-w4) - * Adding a hack here to return w0 without modification - * TODO: analyse the use of return value from arch_swap - * Make sure the return value is not being intrepreted - * wrongly - */ - __asm__ volatile( - "mov.l w1, [w15++]\n\t" - "mov.l w2, [w15++]\n\t" - ); - _current->arch.swapped_from_thread = 0; - result = _current->arch.swap_return_value; - irq_unlock(_current->arch.cpu_level); - __asm__ volatile( - "mov.l [--w15], w2\n\t" - "mov.l [--w15], w1\n\t" - ); - return result; - - /* Context switch is performed here. Returning implies the - * thread has been context-switched-in again. - */ -} diff --git a/arch/dspic/include/kernel_arch_swap.h b/arch/dspic/include/kernel_arch_swap.h deleted file mode 100644 index 8a44a4e7e28e2..0000000000000 --- a/arch/dspic/include/kernel_arch_swap.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2025, Microchip Technology Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Private kernel arch swap functions - * - * This file contains function helpers for dspic arch specific thread swap - * helper functions - */ - -#ifndef ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ -#define ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ - -#ifndef _ASMLANGUAGE - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#include "kswap.h" - -#if defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK512MPS512) -#define RAM_END "0x00013FFC" -#elif defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK128MC106) -#define RAM_END "0x00007FFC" -#endif - - -#define NUM_TEMP_REGS 3 -extern int swap_working_set[NUM_TEMP_REGS]; - -static inline __attribute__((always_inline)) void z_dspic_save_context(void) -{ - /*Adjust stack for co-operative swap*/ - __asm__ volatile( - /*Check if in interrupt context*/ - "mov.l w0, [w15++]\n\t" - "mov.l #"RAM_END", w0\n\t" - "mov.l w0, SPLIM\n\t" - "mov.l sr, w0\n\t" - "and #0xe0, w0\n\t" - "bra nz, 1f\n\t" - - /*Not in interrupt context*/ - "mov.l [--w15], w0\n\t" - /*This unlink is needed to match esf*/ - "ulnk\n\t" - /*Backup the working reg W0-W2*/ - "mov.l w2, [w15++]\n\t" - "mov.l w1, [w15++]\n\t" - "mov.l w0, [w15++]\n\t" - "mov.l #_swap_working_set, w0\n\t" - "mov.l [--w15], [w0++]\n\t" - "mov.l [--w15], [w0++]\n\t" - "mov.l [--w15], [w0]\n\t" - /*Format SR and LR as its from interrupt*/ - "mov.l [--w15], w1\n\t" - "mov.l sr, [w15++]\n\t" - "mov.l w1, [w15++]\n\t" - "mov.l [w0--], w2\n\t" - "mov.l [w0--], w1\n\t" - "mov.l [w0], w0\n\t" - "mov.l w0, [w15++]\n\t" - - "1:\n\t" - "mov.l [--w15], w0\n\t" - "push RCOUNT\n\t" - "push.l fsr\n\t" - "push.l fcr\n\t" - "mov.l w0, [w15++]\n\t" - "mov.l w1, [w15++]\n\t" - "mov.l w2, [w15++]\n\t" - "mov.l w3, [w15++]\n\t" - "mov.l w4, [w15++]\n\t" - "mov.l w5, [w15++]\n\t" - "mov.l w6, [w15++]\n\t" - "mov.l w7, [w15++]\n\t" - "push.l f0\n\t" - "push.l f1\n\t" - "push.l f2\n\t" - "push.l f3\n\t" - "push.l f4\n\t" - "push.l f5\n\t" - "push.l f6\n\t" - "push.l f7\n\t" - "lnk #0x4\n\t"); - /*in isr lnk is done after esf push*/ - - /* Get the current thread callee_saved context - */ - __asm__ volatile("mov.l #__kernel, w0\n\t" - "mov.l #___cpu_t_current_OFFSET, w1\n\t" - "add w0, w1, w1\n\t" - "mov.l [w1], w2\n\t" - "mov.l #___thread_t_callee_saved_OFFSET, w1\n\t" - "add w2, w1, w1\n\t"); - - /*Save all callee saved registers*/ - __asm__ volatile("mov.l w8, [w1++]\n\t" - "mov.l w9, [w1++]\n\t" - "mov.l w10, [w1++]\n\t" - "mov.l w11, [w1++]\n\t" - "mov.l w12, [w1++]\n\t" - "mov.l w13, [w1++]\n\t" - "mov.l w14, [w1++]\n\t" - - "mov.l f8, [w1++]\n\t" - "mov.l f9, [w1++]\n\t" - "mov.l f10, [w1++]\n\t" - "mov.l f11, [w1++]\n\t" - "mov.l f12, [w1++]\n\t" - "mov.l f13, [w1++]\n\t" - "mov.l f14, [w1++]\n\t" - "mov.l f15, [w1++]\n\t" - "mov.l f16, [w1++]\n\t" - "mov.l f17, [w1++]\n\t" - "mov.l f18, [w1++]\n\t" - "mov.l f19, [w1++]\n\t" - "mov.l f20, [w1++]\n\t" - "mov.l f21, [w1++]\n\t" - "mov.l f22, [w1++]\n\t" - "mov.l f23, [w1++]\n\t" - "mov.l f24, [w1++]\n\t" - "mov.l f25, [w1++]\n\t" - "mov.l f26, [w1++]\n\t" - "mov.l f27, [w1++]\n\t" - "mov.l f28, [w1++]\n\t" - "mov.l f29, [w1++]\n\t" - "mov.l f30, [w1++]\n\t" - "mov.l f31, [w1++]\n\t" - - "mov.l #RCOUNT, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #CORCON, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #MODCON, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #XMODSRT, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #XMODEND, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #YMODSRT, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #YMODEND, w2\n\t" - "mov.l [w2], [w1++]\n\t" - "mov.l #XBREV, w2\n\t" - "mov.l [w2], [w1++]\n\t" - - "slac.l A, [W1++]\n\t" - "sac.l A, [W1++]\n\t" - "suac.l A, [W1++]\n\t" - "slac.l B, [W1++]\n\t" - "sac.l B, [W1++]\n\t" - "suac.l B, [W1++]\n\t" - - "mov.l w15, [w1++]\n\t" - "mov.l w14, [w1++]\n\t" - "mov.l #SPLIM, w2\n\t" - "mov.l [w2], [w1++]\n\t"); -} - -static inline __attribute__((always_inline)) void z_dspic_restore_context(void) -{ - /* Get the current thread callee_saved context - */ - __asm__ volatile("mov.l #__kernel, w0\n\t" - "mov.l #___cpu_t_current_OFFSET, w1\n\t" - "add w0, w1, w1\n\t" - "mov.l [w1], w2\n\t" - "mov.l #___thread_t_callee_saved_OFFSET, w1\n\t" - "add w2, w1, w1\n\t"); - - /*Restore all registers*/ - __asm__ volatile("mov.l [w1++], w8\n\t" - "mov.l [w1++], w9\n\t" - "mov.l [w1++], w10\n\t" - "mov.l [w1++], w11\n\t" - "mov.l [w1++], w12\n\t" - "mov.l [w1++], w13\n\t" - "mov.l [w1++], w14\n\t" - - "mov.l [w1++], f8\n\t" - "mov.l [w1++], f9\n\t" - "mov.l [w1++], f10\n\t" - "mov.l [w1++], f11\n\t" - "mov.l [w1++], f12\n\t" - "mov.l [w1++], f13\n\t" - "mov.l [w1++], f14\n\t" - "mov.l [w1++], f15\n\t" - "mov.l [w1++], f16\n\t" - "mov.l [w1++], f17\n\t" - "mov.l [w1++], f18\n\t" - "mov.l [w1++], f19\n\t" - "mov.l [w1++], f20\n\t" - "mov.l [w1++], f21\n\t" - "mov.l [w1++], f22\n\t" - "mov.l [w1++], f23\n\t" - "mov.l [w1++], f24\n\t" - "mov.l [w1++], f25\n\t" - "mov.l [w1++], f26\n\t" - "mov.l [w1++], f27\n\t" - "mov.l [w1++], f28\n\t" - "mov.l [w1++], f29\n\t" - "mov.l [w1++], f30\n\t" - "mov.l [w1++], f31\n\t" - - "mov.l #RCOUNT, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #CORCON, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #MODCON, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #XMODSRT, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #XMODEND, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #YMODSRT, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #YMODEND, w2\n\t" - "mov.l [w1++], [w2]\n\t" - "mov.l #XBREV, w2\n\t" - "mov.l [w1++], [w2]\n\t" - - "clr A\n\t" - "clr B\n\t" - "llac.l [w1++], A\n\t" - "lac.l [w1++], A\n\t" - "luac.l [w1++], A\n\t" - "llac.l [w1++], B\n\t" - "lac.l [w1++], B\n\t" - "luac.l [w1++], B\n\t" - - "mov.l [w1++], w15\n\t" - "mov.l [w1++], w14\n\t" - "mov.l #SPLIM, w2\n\t" - "mov.l [w1++], [w2]\n\t"); - - /*pop exception/swap saved stack frame*/ - __asm__ volatile( - /*in isr the unlink is done before esf pop*/ - "ulnk\n\t" - /*Thread context*/ - "pop.l f7\n\t" - "pop.l f6\n\t" - "pop.l f5\n\t" - "pop.l f4\n\t" - "pop.l f3\n\t" - "pop.l f2\n\t" - "pop.l f1\n\t" - "pop.l f0\n\t" - "mov.l [--w15], w7\n\t" - "mov.l [--w15], w6\n\t" - "mov.l [--w15], w5\n\t" - "mov.l [--w15], w4\n\t" - "mov.l [--w15], w3\n\t" - "mov.l [--w15], w2\n\t" - "mov.l [--w15], w1\n\t" - "mov.l [--w15], w0\n\t" - "pop.l fcr\n\t" - "pop.l fsr\n\t" - "pop RCOUNT\n\t" - - /* Check context and only pop the - * esf if in thread context - */ - "mov.l w0, [w15++]\n\t" - "mov.l sr, w0\n\t" - "and #0xe0, w0\n\t" - "mov.l [--w15], w0\n\t" - "bra nz, 1f\n\t" - - /*Backup the working reg W0-W2*/ - "mov.l w2, [w15++]\n\t" - "mov.l w1, [w15++]\n\t" - "mov.l w0, [w15++]\n\t" - "mov.l #_swap_working_set, w0\n\t" - "mov.l [--w15], [w0++]\n\t" - "mov.l [--w15], [w0++]\n\t" - "mov.l [--w15], [w0]\n\t" - /*Format SR and LR as its from interrupt*/ - "mov.l [--w15], w1\n\t" - "mov.l [--w15], w2\n\t" - "mov.l w2, sr\n\t" - "mov.l w1, [w15++]\n\t" - "mov.l [w0--], w2\n\t" - "mov.l [w0--], w1\n\t" - "mov.l [w0], w0\n\t" - - "lnk #0x4\n\t" - - /*Interrupt context*/ - "1:\n\t" - "nop\n\t"); -} - -/* routine which swaps the context. Needs to be written in assembly */ -static inline __attribute__((always_inline)) void z_dspic_do_swap(void) -{ - /* Switch to context 0 before starting context save and restore - * This Arch has 7 context and each has banked register sets for w0-w8 - * So in interrupt we are in ctx 1 and need to go to ctx 0 for tasks - */ - __asm__ volatile("CTXTSWP #0x0"); - - z_dspic_save_context(); - - /*Switch to next task in queue*/ - z_current_thread_set(_kernel.ready_q.cache); - - /* It is expected to save current thread's pointer on z_tls_current - * variable because k_current_get() call will get the current thread's - * pointer from this variable if the CONFIG_CURRENT_THREAD_USE_TLS - * is enabled. In ztest k_thread_abort() was trying to abort the - * current thread. - */ -#ifdef CONFIG_CURRENT_THREAD_USE_TLS - /* Thread-local cache of current thread ID, set in z_thread_entry() */ - _set_tls((void *)_current->tls); -#endif - - z_dspic_restore_context(); -} - -#ifdef __cplusplus -} -#endif - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ */ diff --git a/arch/dspic/include/kernel_arch_swap_macro.S b/arch/dspic/include/kernel_arch_swap_macro.S new file mode 100644 index 0000000000000..405a4b524c699 --- /dev/null +++ b/arch/dspic/include/kernel_arch_swap_macro.S @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2025, Microchip Technology Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Private kernel arch swap functions + * + * This file contains function helpers for dspic arch specific thread swap + * helper functions + */ + +#ifndef ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ +#define ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ + +#include +#include + +#if defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK512MPS512) +#define RAM_END 0x00013FFC +#elif defined(CONFIG_BOARD_DSPIC33A_CURIOSITY_P33AK128MC106) +#define RAM_END 0x00007FFC +#endif + +#if defined(_ASMLANGUAGE) + +.equ __kernel_current_OFFSET, __kernel + ___cpu_t_current_OFFSET +.equ __thread_t_arch_cpu_level_OFFSET, ___thread_t_arch_OFFSET + ___thread_arch_t_cpu_level_OFFSET +.equ __kernel_ready_q_cache_OFFSET, __kernel + ___kernel_t_ready_q_OFFSET + \ + ___ready_q_t_cache_OFFSET +.equ __thread_t_arch_swap_return_value_OFFSET, ___thread_t_arch_OFFSET + \ + ___thread_arch_t_swap_return_value_OFFSET +.equ __thread_t_arch_swapped_from_thread_OFFSET, ___thread_t_arch_OFFSET + \ + ___thread_arch_t_swapped_from_thread_OFFSET + +.extern _swap_working_set + +.macro z_dspic_save_caller_saved + push RCOUNT + push.l fsr + push.l fcr + mov.l w0, [w15++] + mov.l w1, [w15++] + mov.l w2, [w15++] + mov.l w3, [w15++] + mov.l w4, [w15++] + mov.l w5, [w15++] + mov.l w6, [w15++] + mov.l w7, [w15++] + push.l f0 + push.l f1 + push.l f2 + push.l f3 + push.l f4 + push.l f5 + push.l f6 + push.l f7 + lnk #0x4 +.endm + +.macro z_dspic_restore_caller_saved + ulnk + pop.l f7 + pop.l f6 + pop.l f5 + pop.l f4 + pop.l f3 + pop.l f2 + pop.l f1 + pop.l f0 + mov.l [--w15], w7 + mov.l [--w15], w6 + mov.l [--w15], w5 + mov.l [--w15], w4 + mov.l [--w15], w3 + mov.l [--w15], w2 + mov.l [--w15], w1 + mov.l [--w15], w0 + pop.l fcr + pop.l fsr + pop RCOUNT +.endm + +.macro z_dspic_get_current_callee_saved + /* Get the current thread callee_saved context + * and store it in w1 + */ + mov.l #__kernel, w0 + mov.l [w0 + ___cpu_t_current_OFFSET], w2 + mov.l #___thread_t_callee_saved_OFFSET, w1 + add w2, w1, w1 +.endm + +.macro z_dspic_save_callee_saved + z_dspic_get_current_callee_saved + + /*Save all callee saved registers*/ + mov.l w8, [w1++] + mov.l w9, [w1++] + mov.l w10, [w1++] + mov.l w11, [w1++] + mov.l w12, [w1++] + mov.l w13, [w1++] + mov.l w14, [w1++] + + mov.l f8, [w1++] + mov.l f9, [w1++] + mov.l f10, [w1++] + mov.l f11, [w1++] + mov.l f12, [w1++] + mov.l f13, [w1++] + mov.l f14, [w1++] + mov.l f15, [w1++] + mov.l f16, [w1++] + mov.l f17, [w1++] + mov.l f18, [w1++] + mov.l f19, [w1++] + mov.l f20, [w1++] + mov.l f21, [w1++] + mov.l f22, [w1++] + mov.l f23, [w1++] + mov.l f24, [w1++] + mov.l f25, [w1++] + mov.l f26, [w1++] + mov.l f27, [w1++] + mov.l f28, [w1++] + mov.l f29, [w1++] + mov.l f30, [w1++] + mov.l f31, [w1++] + + mov.l #RCOUNT, w2 + mov.l [w2], [w1++] + mov.l #CORCON, w2 + mov.l [w2], [w1++] + mov.l #MODCON, w2 + mov.l [w2], [w1++] + mov.l #XMODSRT, w2 + mov.l [w2], [w1++] + mov.l #XMODEND, w2 + mov.l [w2], [w1++] + mov.l #YMODSRT, w2 + mov.l [w2], [w1++] + mov.l #YMODEND, w2 + mov.l [w2], [w1++] + mov.l #XBREV, w2 + mov.l [w2], [w1++] + + slac.l A, [W1++] + sac.l A, [W1++] + suac.l A, [W1++] + slac.l B, [W1++] + sac.l B, [W1++] + suac.l B, [W1++] + + mov.l w15, [w1++] + mov.l w14, [w1++] + mov.l #SPLIM, w2 + mov.l [w2], [w1++] +.endm + +.macro z_dspic_restore_callee_saved + z_dspic_get_current_callee_saved + + /*restore all callee saved registers*/ + mov.l [w1++], w8 + mov.l [w1++], w9 + mov.l [w1++], w10 + mov.l [w1++], w11 + mov.l [w1++], w12 + mov.l [w1++], w13 + mov.l [w1++], w14 + + mov.l [w1++], f8 + mov.l [w1++], f9 + mov.l [w1++], f10 + mov.l [w1++], f11 + mov.l [w1++], f12 + mov.l [w1++], f13 + mov.l [w1++], f14 + mov.l [w1++], f15 + mov.l [w1++], f16 + mov.l [w1++], f17 + mov.l [w1++], f18 + mov.l [w1++], f19 + mov.l [w1++], f20 + mov.l [w1++], f21 + mov.l [w1++], f22 + mov.l [w1++], f23 + mov.l [w1++], f24 + mov.l [w1++], f25 + mov.l [w1++], f26 + mov.l [w1++], f27 + mov.l [w1++], f28 + mov.l [w1++], f29 + mov.l [w1++], f30 + mov.l [w1++], f31 + + mov.l #RCOUNT, w2 + mov.l [w1++], [w2] + mov.l #CORCON, w2 + mov.l [w1++], [w2] + mov.l #MODCON, w2 + mov.l [w1++], [w2] + mov.l #XMODSRT, w2 + mov.l [w1++], [w2] + mov.l #XMODEND, w2 + mov.l [w1++], [w2] + mov.l #YMODSRT, w2 + mov.l [w1++], [w2] + mov.l #YMODEND, w2 + mov.l [w1++], [w2] + mov.l #XBREV, w2 + mov.l [w1++], [w2] + + clr A + clr B + llac.l [W1++], A + lac.l [W1++], A + luac.l [W1++], A + llac.l [W1++], B + lac.l [W1++], B + luac.l [W1++], B + + mov.l [w1++], w15 + mov.l [w1++], w14 + mov.l #SPLIM, w2 + mov.l [w1++], [w2] +.endm + +.macro z_dspic_temp_backup_working_reg + /*Backup the working reg W0-W2*/ + mov.l w2, [w15++] + mov.l w1, [w15++] + mov.l w0, [w15++] + mov.l #_swap_working_set, w0 + mov.l [--w15], [w0++] + mov.l [--w15], [w0++] + mov.l [--w15], [w0] +.endm + +.macro z_dspic_restore_working_reg + mov.l [w0--], w2 + mov.l [w0--], w1 + mov.l [w0], w0 +.endm + +.macro z_dspic_stack_thread_to_irq + ulnk + /*backup the working reg w0-w2*/ + z_dspic_temp_backup_working_reg + /*Format SR and LR as its from interrupt*/ + mov.l [--w15], w1 + mov.l sr, [w15++] + mov.l w1, [w15++] + /*restore the working reg w0-w2*/ + z_dspic_restore_working_reg +.endm + +.macro z_dspic_stack_irq_to_thread + /*backup the working reg w0-w2*/ + z_dspic_temp_backup_working_reg + /*Format SR and LR as its from interrupt*/ + mov.l [--w15], w1 + mov.l [--w15], w2 + mov.l w2, sr + mov.l w1, [w15++] + /*restore the working reg w0-w2*/ + z_dspic_restore_working_reg + lnk #0x4 +.endm + +.macro z_dspic_do_swap + /* Set the SPLIM to end of RAM + * To avoid, stack overflow fault. + */ + mov.l w0, [w15++] + mov.l #RAM_END, w0 + mov.l w0, SPLIM + mov.l [--w15], w0 + /* Switch to context 0 before starting context save and restore + * This Arch has 7 context and each has banked register sets for w0-w8 + * So in interrupt we are in ctx 1 and need to go to ctx 0 for tasks + */ + ctxtswp #0x0 + + /* Save the current context + */ + z_dspic_stack_thread_to_irq + z_dspic_save_caller_saved + z_dspic_save_callee_saved + + /* Switch to next task in queue + * No need to save and restore working registers here + * */ + mov.l #__kernel_ready_q_cache_OFFSET, w2 + mov.l [w2], w2 + mov.l #__kernel_current_OFFSET, w1 + mov.l w2, [w1] + +#ifdef CONFIG_CURRENT_THREAD_USE_TLS + /*Switch the TLS pointer for the task to be swapped*/ + mov.l [w2 + ___thread_t_tls_OFFSET], w0 + rcall __set_tls +#endif + + /* Restore next thread context + */ + z_dspic_restore_callee_saved + z_dspic_restore_caller_saved + z_dspic_stack_irq_to_thread +.endm + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_ARCH_DSPIC_INCLUDE_KERNEL_ARCH_SWAP_H_ */ diff --git a/boards/microchip/dspic33/dspic33a_curiosity/board.yml b/boards/microchip/dspic33/dspic33a_curiosity/board.yml index 412a13838177c..85e0b848fffab 100644 --- a/boards/microchip/dspic33/dspic33a_curiosity/board.yml +++ b/boards/microchip/dspic33/dspic33a_curiosity/board.yml @@ -4,5 +4,4 @@ board: vendor: microchip socs: - name: p33ak128mc106 - - name: p33ak256mc506 - name: p33ak512mps512 diff --git a/boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK128MC106.webp b/boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK128MC106.webp new file mode 100644 index 0000000000000000000000000000000000000000..0bf4c782b24646302223ac3a667cffaf716b0d33 GIT binary patch literal 13000 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 literal 0 HcmV?d00001 diff --git a/boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK512MPS512.webp.license b/boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK512MPS512.webp.license new file mode 100644 index 0000000000000..917f5636f5564 --- /dev/null +++ b/boards/microchip/dspic33/dspic33a_curiosity/doc/img/dsPIC33AK512MPS512.webp.license @@ -0,0 +1,4 @@ +** +* Copyright (c) 2025, Microchip Technology Inc. +* SPDX-License-Identifier: Apache-2.0 +*/ \ No newline at end of file diff --git a/boards/microchip/dspic33/dspic33a_curiosity/doc/img/ev74h48a.webp b/boards/microchip/dspic33/dspic33a_curiosity/doc/img/ev74h48a.webp new file mode 100644 index 0000000000000000000000000000000000000000..f61a8b895fe025e7696417675b91a9fec47da97d GIT binary patch literal 66802 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 YLn)dYUy_j&Jt7n5r7~6!AcOz_0CJ+GtpET3 literal 0 HcmV?d00001 diff --git a/boards/microchip/dspic33/dspic33a_curiosity/doc/index.rst b/boards/microchip/dspic33/dspic33a_curiosity/doc/index.rst new file mode 100644 index 0000000000000..30b2adeb89780 --- /dev/null +++ b/boards/microchip/dspic33/dspic33a_curiosity/doc/index.rst @@ -0,0 +1,207 @@ +.. zephyr:board:: dspic33a_curiosity + +Overview +******** + +The Curiosity Platform Development Board (EV74H48A) is a +full-featured development and demonstration platform enabling +customers to explore the capabilities of the dsPIC33A Digital +Signal Controller (DSC) family and also the PIC32A MCU family. +This board requires a DIM (Daughter Interface Module): +dsPIC33AK128MC106 or dsPIC33AK512MPS512 + +Hardware +******** + + - Baseboard + - dsPIC33A Curiosity Board + - Supported DIM Modules + - dsPIC33AK128MC106 + - dsPIC33AK512MPS512 + +dsPIC33AK128MC106 + - High-Performance dsPIC33A DSP CPU + - 16-bit dsPIC33 core compatible + - Non-paged linear Data/Flash 24-bit addressing space + - 16-bit/32-bit instructions for optimized code size and performance + - 32-bit Working Registers + - Program flash: 128 KB + - RAM: 16KB + - 3 Instances of UARTs + - One Dedicated 32-bit Timer/Counter + - Four Single Output Capture/Compare/PWM/Timer (SCCP) Modules + - The POSC and Internal FRC oscillators can use the on-chip PLL to achieve higher operating speeds. + +dsPIC33AK512MPS512 + - High-Performance dsPIC33A DSP CPU + - 16-bit dsPIC33 core compatible + - Linear 24-bit program/data memory addressing space (no paging required) + - 16-bit/32-bit instructions for optimized code size and performance + - 32-bit Working Registers + - Program flash: 512 KB + - RAM: 64KB + - 3 Instances of UARTs + - Three Dedicated 32-Bit Timers/Counters + - Single (SCCP) and Multiple (MCCP) Output Capture/Compare/PWM/Timer Modules + - Two 1.6 GHz PLLs for Peripheral which can be clocked from the FRC or a Crystal Oscillator + +For more information about the Baseboard please see `Curiosity Platform Development Board User's Guide`_ +For more information about the dsPIC33AK128MC106 please see `dsPIC33AK128MC106 Family Data Sheet`_ +For more information about the dsPIC33AK512MPS512 please see `dsPIC33AK512MPS512 Family Data Sheet`_ + +Supported Features +================== + +.. zephyr:board-supported-hw:: + +Connections and IOs +=================== +The dsPIC33A Curiosity board requires one of the following: dsPIC33AK128MC106 or dsPIC33AK512MPS512 + + - Insert the appropriate DIM board into the 120-pin socket, ensuring correct orientation. + - Connect the Curiosity board to the host PC via USB. + - Power and programming are handled through the on-board PKOB debugger. + - Remove the jumper ``J28`` to enable the debugger. + - ``J25`` is a 3-pin jumper used to choose the power source for the board. + Place the jumper on pins 1-2 to use USB power (5V_USB). + +System Clock +============ + - The dsPIC33AK128MC106/dsPIC33AK512MPS512 uses its internal 8 MHz FRC oscillator as the default clock source. + - They also support multiple clock sources and an on-chip PLL, allowing the system and peripherals to operate at higher performance levels. + - Peripheral clocks (Fast, Standard, Slow) are derived via fixed divisors. + - See Processor clock control register in chapter ``oscillator module`` of the data sheet. + +Serial Port +=========== + - The dsPIC33A Curiosity board provides a UART interface for console output and communication with a PC. + - The serial interface can be accessed through the baseboard's DIM connector: + - UART1 is configured for serial logs. + - Pin 102 on base board USB to UART Converter TX + - Pin 100 on base board USB to UART Converter RX + +For more information about the DIM pins please see `dsPIC33AK128MC106 DIM schematics`_ `dsPIC33AK512MPS512 DIM schematics`_ + +ToolChain Setup +=============== + - Download and install the latest ``MPLABXIDE`` where you get the ``XC-DSC`` compiler from Microchip + - Go to the official Microchip MPLAB X IDE please see `MPLABxIDE Installation`_ + - The XC-DSC toolchain is not part of the Zephyr SDK by default, + so the path to the compiler must be added manually. + +Setting the Toolchain Variant +============================= + - Zephyr uses the variable :makevar:`ZEPHYR_TOOLCHAIN_VARIANT` to select which + toolchain to use. For this board, the variant name is ``xcdsc``. + + - To specify it on the command line: + + .. code-block:: console + + west build -b dspic33a_curiosity/ samples/hello_world -- -DZEPHYR_TOOLCHAIN_VARIANT=xcdsc + +Setting the Toolchain Path +========================== +#. The XC-DSC compiler must be installed separately from Zephyr. The installation + directory should be provided using the :makevar:`ZEPHYR_TOOLCHAIN_PATH` variable. + +#. Typical installation paths are: + +- **Windows**: ``C:\Program Files\Microchip\xc-dsc\`` +- **Linux**: ``/opt/microchip/xc16/`` + +#. To specify it on the command line: + + .. code-block:: console + + west build -p always -b dspic33a_curiosity/ samples/hello_world/ -- -DZEPHYR_TOOLCHAIN_VARIANT=xcdsc -DXCDSC_TOOLCHAIN_PATH=/opt/microchip/xc-dsc/ + +Building +======== + +#. Build :zephyr:code-sample:`hello_world` application as you normally do. + +#. After a successful build, the following files are produced: + build/zephyr/zephyr.elf this will be used to flash + +#. To build sample on the command line: + + .. code-block:: console + + west build -p always -b dspic33a_curiosity/ samples/hello_world/ -- -DZEPHYR_TOOLCHAIN_VARIANT=xcdsc -DXCDSC_TOOLCHAIN_PATH=/opt/microchip/xc-dsc/ + +Flashing +======== +#. Run your favorite terminal program to listen for output. + Under Linux the terminal should be :code:`/dev/ttyACM1`. + + For example: + + .. code-block:: console + + $ minicom -D /dev/ttyACM1 -o + + The -o option tells minicom not to send the modem initialization + string. Connection should be configured as follows: + + - Speed: 115200 + - Data: 8 bits + - Parity: None + - Stop bits: 1 + +#. Flash your board using ``west`` from the second terminal window. + Split first and second terminal windows to view both of them. + + .. code-block:: console + + $ west flash + +#. You should see ``"Hello World! "`` in the first terminal window. + If you don't see this message, press the Reset button and the message should appear. + +Debugging +========= +#. This board supports application flashing and debugging + using the Microchip Debugger (MDB) command-line tool, which is part of the + MPLAB X installation. + +#. MDB can be used to program and debug Zephyr applications through a simple + command's executed in a terminal. + + .. code-block:: console + + $ mdb + - Device dsPIC33AK128MC106 + - Hwtool pkob4 + - Program build/zephyr/zephyr.elf + - run + - quit + +#. The commands performs the following actions + + - Connects to the target device (dsPIC33AK128MC106). + - Loads the hardware debugger (PKOB4). + - Programs the compiled Zephyr ELF binary. + - Starts program execution on the target. + - Exits the debugger session. + +For more information about MDB please see `Microchip Debugger (MDB) User's Guide`_ + +References +********** +.. target-notes:: + +.. _Curiosity Platform Development Board User's Guide: + https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/UserGuides/Curiosity-Platform-Development-Board-Users-Guide-DS70005562.pdf +.. _dsPIC33AK128MC106 Family Data Sheet: + https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/DataSheets/dsPIC33AK128MC106-Family-Data-Sheet-DS70005539.pdf +.. _dsPIC33AK128MC106 DIM schematics: + https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/InformationSheet/dsPIC33AK128MC106-General-Purpose-DIM-Info-Sheet-DS70005556.pdf +.. _dsPIC33AK512MPS512 Family Data Sheet: + https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/DataSheets/dsPIC33AK512MPS512-Family-Data-Sheet-DS70005591.pdf +.. _dsPIC33AK512MPS512 DIM schematics: + https://ww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/InformationSheet/dsPIC33AK512MPS512-General-Purpose-DIM-Info-Sheet-DS70005563.pdf +.. _MPLABxIDE Installation : + https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide +.. _Microchip Debugger (MDB) User's Guide: + https://www.microchip.com/content/dam/mchp/documents/DEV/ProductDocuments/UserGuides/50002102G.pdf diff --git a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc106.dts b/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc106.dts index ff347435c1628..d6f010061b845 100644 --- a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc106.dts +++ b/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc106.dts @@ -80,7 +80,6 @@ }; &timer1 { - clock-frequency = <8000000>; status = "okay"; }; diff --git a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc506.dts b/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc506.dts deleted file mode 100644 index 9213a07beb6d8..0000000000000 --- a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak128mc506.dts +++ /dev/null @@ -1 +0,0 @@ -/*Nothing here */ diff --git a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak512mps512.dts b/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak512mps512.dts index 143b68997098b..c57d41379610e 100644 --- a/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak512mps512.dts +++ b/boards/microchip/dspic33/dspic33a_curiosity/dspic33a_curiosity_p33ak512mps512.dts @@ -79,7 +79,6 @@ }; &timer1 { - clock-frequency = <8000000>; status = "okay"; }; diff --git a/cmake/compiler/xcdsc/generic.cmake b/cmake/compiler/xcdsc/generic.cmake index 043f88a5fd6bd..38f036d22ba2a 100644 --- a/cmake/compiler/xcdsc/generic.cmake +++ b/cmake/compiler/xcdsc/generic.cmake @@ -35,7 +35,7 @@ function(find_dspic33_dfp) set(_home "$ENV{HOME}") if(WIN32 AND NOT _home) set(_home "$ENV{USERPROFILE}") - file(TO_CMAKE_PATH "${_home}" _home) + file(TO_CMAKE_PATH "${_home}" _home) endif() # Root search list: HOME first (highest priority), then system roots @@ -155,24 +155,24 @@ function(find_dspic33_dfp) set(${FD_OUT_ROOT} "${DFP_ROOT}" PARENT_SCOPE) endfunction() -if ("${BOARD_QUALIFIERS}" MATCHES "/p33ak128mc106" AND - "${BOARD}" MATCHES "dspic33a_curiosity") - set(TARGET_CPU "33AK128MC106") - find_dspic33_dfp( - OUT_INFO C30_DEVICE_INFO - OUT_ROOT DFP_ROOT - ARCHES AK - FAMILIES MC - ) +if("${BOARD_QUALIFIERS}" MATCHES "/p33ak128mc106" AND + "${BOARD}" MATCHES "dspic33a_curiosity") + set(TARGET_CPU "33AK128MC106") + find_dspic33_dfp( + OUT_INFO C30_DEVICE_INFO + OUT_ROOT DFP_ROOT + ARCHES AK + FAMILIES MC + ) elseif("${BOARD_QUALIFIERS}" MATCHES "/p33ak512mps512" AND - "${BOARD}" MATCHES "dspic33a_curiosity") - set(TARGET_CPU "33AK512MPS512") - find_dspic33_dfp( - OUT_INFO C30_DEVICE_INFO - OUT_ROOT DFP_ROOT - ARCHES AK - FAMILIES MP - ) + "${BOARD}" MATCHES "dspic33a_curiosity") + set(TARGET_CPU "33AK512MPS512") + find_dspic33_dfp( + OUT_INFO C30_DEVICE_INFO + OUT_ROOT DFP_ROOT + ARCHES AK + FAMILIES MP + ) endif() message(STATUS "DFP file in ${C30_DEVICE_INFO}") message(STATUS "DFP path ${DFP_ROOT}") @@ -182,7 +182,7 @@ set(ENV{DFP_ROOT} "${DFP_ROOT}") set(ENV{TARGET_CPU} "${TARGET_CPU}") set(CMAKE_C_FLAGS "-D__XC_DSC__ -mdfp=\"${DFP_ROOT}/xc16\"" CACHE STRING "" FORCE) -set(CMAKE_ASM_FLAGS "-mdfp=\"${DFP_ROOT}/xc16\"" CACHE STRING "" FORCE) +set(CMAKE_ASM_FLAGS "-D__XC_DSC__ -mdfp=\"${DFP_ROOT}/xc16\"" CACHE STRING "" FORCE) # Append to DTS preprocessor flags with DFP path if(DEFINED DTS_EXTRA_CPPFLAGS AND NOT "${DTS_EXTRA_CPPFLAGS}" STREQUAL "") @@ -195,17 +195,17 @@ find_program(CMAKE_C_COMPILER xc-dsc-gcc PATHS ${XCDSC_TOOLCHAIN_PATH}/bin/ NO_D # Get compiler version execute_process( - COMMAND ${CMAKE_C_COMPILER} --version - OUTPUT_VARIABLE XCDSC_VERSION_STR - ERROR_VARIABLE XCDSC_VERSION_ERR - OUTPUT_STRIP_TRAILING_WHITESPACE ) + COMMAND ${CMAKE_C_COMPILER} --version + OUTPUT_VARIABLE XCDSC_VERSION_STR + ERROR_VARIABLE XCDSC_VERSION_ERR + OUTPUT_STRIP_TRAILING_WHITESPACE ) # Verify that the installed version is v3.30 or higher if("${XCDSC_VERSION_STR}" MATCHES ".*v([0-9]+)\\.([0-9]+).*") - string(REGEX REPLACE ".*v([0-9]+)\\.([0-9]+).*" "\\1\\2" __XCDSC_VERSION__ "${XCDSC_VERSION_STR}") - math(EXPR XCDSC_VERSION_INT "${__XCDSC_VERSION__}") - if(XCDSC_VERSION_INT LESS 330) - message(FATAL_ERROR "XC-DSC compiler v3.30 or newer is required. Found version: ${XCDSC_VERSION_STR}") - endif() + string(REGEX REPLACE ".*v([0-9]+)\\.([0-9]+).*" "\\1\\2" __XCDSC_VERSION__ "${XCDSC_VERSION_STR}") + math(EXPR XCDSC_VERSION_INT "${__XCDSC_VERSION__}") + if(XCDSC_VERSION_INT LESS 330) + message(FATAL_ERROR "XC-DSC compiler v3.30 or newer is required. Found version: ${XCDSC_VERSION_STR}") + endif() else() - message(FATAL_ERROR "Unable to detect XC-DSC compiler version from: '${XCDSC_VERSION_STR}'") + message(FATAL_ERROR "Unable to detect XC-DSC compiler version from: '${XCDSC_VERSION_STR}'") endif() diff --git a/cmake/toolchain/xcdsc/Kconfig b/cmake/toolchain/xcdsc/Kconfig index 923c90caf1c82..7ea14243f02c5 100644 --- a/cmake/toolchain/xcdsc/Kconfig +++ b/cmake/toolchain/xcdsc/Kconfig @@ -10,6 +10,8 @@ config PICOLIBC_SUPPORTED def_bool y help XC-DSC toolchain supports picolib for C development. +config LIBC_ERRNO + default y config TOOLCHAIN_XCDSC_SUPPORTS_THREAD_LOCAL_STORAGE bool "XC-DSC toolchain supports TLS" def_bool y @@ -17,3 +19,7 @@ config TOOLCHAIN_XCDSC_SUPPORTS_THREAD_LOCAL_STORAGE help Set this if the XC-DSC toolchain being used for the build supports thread local storage. +choice LIBC_IMPLEMENTATION + prompt "C Library Implementation" + default EXTERNAL_LIBC +endchoice diff --git a/drivers/gpio/Kconfig.mchp_dspic b/drivers/gpio/Kconfig.mchp_dspic index d36a3461852ea..9e819de4773b1 100644 --- a/drivers/gpio/Kconfig.mchp_dspic +++ b/drivers/gpio/Kconfig.mchp_dspic @@ -5,5 +5,6 @@ config GPIO_DSPIC bool "dsPIC33A GPIO driver" default y + depends on DT_HAS_MICROCHIP_DSPIC_GPIO_ENABLED help Enable support for the dsPIC33A GPIO driver. diff --git a/drivers/pinctrl/pinctrl_mchp_dspic33_g1.c b/drivers/pinctrl/pinctrl_mchp_dspic33_g1.c index e57676d30df7c..5f5d72c2adef9 100644 --- a/drivers/pinctrl/pinctrl_mchp_dspic33_g1.c +++ b/drivers/pinctrl/pinctrl_mchp_dspic33_g1.c @@ -94,7 +94,7 @@ static int pinctrl_configure_pin(pinctrl_soc_pin_t soc_pin) ret = -EINVAL; } - return 0; + return ret; } int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) @@ -105,6 +105,9 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp for (uint8_t i = 0U; i < pin_cnt; i++) { ret = pinctrl_configure_pin(pins[i]); + if (ret) { + break; + } } return ret; diff --git a/drivers/serial/Kconfig.dspic_uart b/drivers/serial/Kconfig.dspic_uart index f97564d98aa9f..627df96e60afb 100644 --- a/drivers/serial/Kconfig.dspic_uart +++ b/drivers/serial/Kconfig.dspic_uart @@ -4,6 +4,7 @@ config UART_DSPIC bool "dsPIC33A UART driver" default y + depends on DT_HAS_MICROCHIP_DSPIC33_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select PINCTRL diff --git a/drivers/serial/uart_mchp_dspic33_g1.c b/drivers/serial/uart_mchp_dspic33_g1.c index 861a4bf1de927..228b635510ef9 100644 --- a/drivers/serial/uart_mchp_dspic33_g1.c +++ b/drivers/serial/uart_mchp_dspic33_g1.c @@ -303,9 +303,10 @@ static int uart_dspic_poll_in(const struct device *dev, unsigned char *c) int ret_val; key = k_spin_lock(&lock); - /* If receiver buffer is empty, return -1 */ + if ((*UxSTA & BIT_RXBE) != 0U) { - ret_val = -EPERM; + /* uart_poll_in api expects to return -1, if receiver buffer is empty */ + ret_val = -1; } else { diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index 4b90f9d54c138..c830805140a5b 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -23,7 +23,6 @@ zephyr_library_sources_ifdef(CONFIG_ITE_IT8XXX2_TIMER ite_it8xxx2_timer.c) zephyr_library_sources_ifdef(CONFIG_LEON_GPTIMER leon_gptimer.c) zephyr_library_sources_ifdef(CONFIG_LITEX_TIMER litex_timer.c) zephyr_library_sources_ifdef(CONFIG_MCHP_DSPIC33_TIMER mchp_dspic33_timer.c) -zephyr_library_sources_ifdef(CONFIG_MCHP_MEC5_KTIMER mchp_mec5_ktimer.c) zephyr_library_sources_ifdef(CONFIG_MCHP_XEC_RTOS_TIMER mchp_xec_rtos_timer.c) zephyr_library_sources_ifdef(CONFIG_MCHP_SAM_PIT64B_TIMER mchp_sam_pit64b_timer.c) zephyr_library_sources_ifdef(CONFIG_MCUX_LPTMR_TIMER mcux_lptmr_timer.c) diff --git a/drivers/timer/mchp_dspic33_timer.c b/drivers/timer/mchp_dspic33_timer.c index 873d3c6f782db..7e1f47c6a1bda 100644 --- a/drivers/timer/mchp_dspic33_timer.c +++ b/drivers/timer/mchp_dspic33_timer.c @@ -18,10 +18,14 @@ #define TIMER1_CYCLES_PER_TICK \ ((sys_clock_hw_cycles_per_sec() + \ - ((2U * DT_INST_PROP(0, prescalar) * CONFIG_SYS_CLOCK_TICKS_PER_SEC) / 2U)) / \ - (2U * DT_INST_PROP(0, prescalar) * CONFIG_SYS_CLOCK_TICKS_PER_SEC)) + ((2U * DT_INST_PROP(0, prescaler) * CONFIG_SYS_CLOCK_TICKS_PER_SEC) / 2U)) / \ + (2U * DT_INST_PROP(0, prescaler) * CONFIG_SYS_CLOCK_TICKS_PER_SEC)) +#define TIMER1_BASE DT_REG_ADDR(DT_NODELABEL(timer1)) #define MAX_TIMER_CLOCK_CYCLES 0xFFFFFFFFU +#define TMRx_OFFSET 0x0004U +#define PRx_OFFSET 0x0008U + static struct k_spinlock lock; static uint64_t total_cycles; static uint64_t prev_announced_cycle; @@ -31,6 +35,12 @@ static uint32_t un_announced_cycles; const int32_t z_sys_timer_irq_for_test = DT_INST_IRQN(0); #endif +/* Timer configuration from DeviceTree */ +static volatile uint32_t *TxCON = (uint32_t *)TIMER1_BASE; +static volatile uint32_t *TMRx = (uint32_t *)(TIMER1_BASE + TMRx_OFFSET); +static volatile uint32_t *PRx = (uint32_t *)(TIMER1_BASE + PRx_OFFSET); + +/* Map prescaler value to bits */ static uint8_t map_prescaler_to_bits(uint32_t val) { uint8_t ret_val; @@ -55,27 +65,40 @@ static uint8_t map_prescaler_to_bits(uint32_t val) return ret_val; } -static void configure_timer1(void) +/* Configure timer registers */ +static void configure_timer(uint32_t cycles) { - const uint32_t timer_count = (uint32_t)TIMER1_CYCLES_PER_TICK - 1U; + /* Turn off timer and clear TMR register */ + *TxCON &= ~(0x8000U); + *TMRx = 0; - /* clear timer control and timer count register */ - T1CONbits.ON = 0; + /* set the timeout count */ + *PRx = cycles - 1U; - /* Select standard peripheral clock */ - T1CONbits.TCS = 0; - T1CONbits.TCKPS = map_prescaler_to_bits(DT_INST_PROP(0, prescalar)); - TMR1 = 0; - IEC1bits.T1IE = 0; - IFS1bits.T1IF = 0; + /* Start the timer. */ + *TxCON |= 0x8000U; +} - /* set the time out count */ - PR1 = (uint32_t)timer_count; +static void initialize_timer(void) +{ + /* Standard peripheral clock */ + *TxCON &= ~(0x0002U); + *TxCON |= (map_prescaler_to_bits(DT_INST_PROP(0, prescaler)) << 4U); - /* Start the timer. */ - T1CONbits.ON = 1; + configure_timer(TIMER1_CYCLES_PER_TICK); } +/* Busy wait */ +#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT +void arch_busy_wait(uint32_t usec_to_wait) +{ + ARG_UNUSED(usec_to_wait); + __asm__ volatile("sl.l w0,#0x03,w0\n\t" + "repeat.w w0\n\t" + "neop\n\n\t"); +} +#endif + /** * @brief Return the current 32-bit cycle count from a hardware timer */ @@ -85,11 +108,11 @@ uint32_t sys_clock_cycle_get_32(void) k_spinlock_key_t key; key = k_spin_lock(&lock); - cycles = (uint32_t)total_cycles + (PR1 * (uint32_t)arch_dspic_irq_isset(DT_INST_IRQN(0))) + - TMR1; + cycles = (uint32_t)total_cycles + (*PRx * (uint32_t)arch_dspic_irq_isset(DT_INST_IRQN(0))) + + *TMRx; k_spin_unlock(&lock, key); - return cycles * 2U * DT_INST_PROP(0, prescalar); + return cycles * 2U * DT_INST_PROP(0, prescaler); } uint32_t sys_clock_elapsed(void) @@ -110,11 +133,10 @@ uint32_t sys_clock_elapsed(void) * Number of cycles per tick */ ticks_elapsed = ((uint32_t)(total_cycles - prev_announced_cycle) + - (uint32_t)(TMR1 + ((uint32_t)TIMER1_CYCLES_PER_TICK / 10U))) / + (uint32_t)(*TMRx + (TIMER1_CYCLES_PER_TICK / 10U))) / ((uint32_t)TIMER1_CYCLES_PER_TICK); k_spin_unlock(&lock, key); } while (0); - return ticks_elapsed; } @@ -128,7 +150,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) do { if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - /* if it is not in tickles mode, no need to change the + /* If it is not in tickles mode, no need to change the * Timeout interval, it will periodically interrupt * At every tick */ @@ -138,23 +160,17 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) /* check if it is K_TICKS_FOREVER, is so set to max cycles */ next_count = (ticks == K_TICKS_FOREVER) ? MAX_TIMER_CLOCK_CYCLES - : (uint32_t)(ticks * TIMER1_CYCLES_PER_TICK); - key = k_spin_lock(&lock); - total_cycles = total_cycles + (uint64_t)TMR1; - un_announced_cycles = un_announced_cycles + TMR1; + : (uint32_t)((uint32_t)(ticks * TIMER1_CYCLES_PER_TICK) + 1U); - /* clear the timer1 counter register and set the period register to the - * New timeout value. This should be done with TIMER1 disabled - */ - T1CONbits.ON = 0; - TMR1 = 0; - PR1 = next_count; - T1CONbits.ON = 1; + key = k_spin_lock(&lock); + total_cycles = total_cycles + (uint64_t)*TMRx; + un_announced_cycles = un_announced_cycles + *TMRx; + configure_timer(next_count); k_spin_unlock(&lock, key); } while (0); } -/* Timer1 ISR */ +/* ISR */ static void timer1_isr(const void *arg) { uint32_t elapsed_ticks; @@ -167,51 +183,35 @@ static void timer1_isr(const void *arg) * Of cycles per tick. For tickles, the period would have been set * To the next event time. */ - elapsed_ticks = (uint32_t)(un_announced_cycles + PR1) / (uint32_t)TIMER1_CYCLES_PER_TICK; + elapsed_ticks = (uint32_t)(un_announced_cycles + *PRx) / (uint32_t)TIMER1_CYCLES_PER_TICK; key = k_spin_lock(&lock); - total_cycles = total_cycles + (uint64_t)PR1; + total_cycles = total_cycles + (uint64_t)*PRx; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { /* If not in tickles mode set the interrupt to happen at the next * Tick. Clear the timer1 counter register and set the period register * to the tick timeout value. This should be done with TIMER1 disabled. */ - T1CONbits.ON = 0; - PR1 = (uint32_t)TIMER1_CYCLES_PER_TICK; - T1CONbits.ON = 1; + *TxCON &= ~(0x8000U); + *PRx = TIMER1_CYCLES_PER_TICK; + *TxCON |= 0x8000U; } k_spin_unlock(&lock, key); - /* - * The hardware timer (TMR1/PR1) has a limited range. If PR1 hits its maximum - * value (MAX_TIMER_CLOCK_CYCLES), we must stop and restart the timer with this - * max period to prevent overflow/wraparound issues. - * - * Otherwise, if PR1 is within range, we reset un_announced_cycles and call + /* If PR1 is within range, we reset un_announced_cycles and call * sys_clock_announce(elapsed_ticks) to inform the kernel about the elapsed * system ticks. This keeps the Zephyr kernel’s time accounting accurate. */ - if (PR1 != MAX_TIMER_CLOCK_CYCLES) { - T1CONbits.ON = 0; + if (*PRx != MAX_TIMER_CLOCK_CYCLES) { + *TxCON &= ~(0x8000U); un_announced_cycles = 0; prev_announced_cycle = total_cycles; sys_clock_announce(elapsed_ticks); } } -#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT -void arch_busy_wait(uint32_t usec_to_wait) -{ - uint32_t cycles_to_wait = sys_clock_hw_cycles_per_sec() / USEC_PER_SEC * usec_to_wait; - - while (cycles_to_wait-- > 0) { - __asm__ volatile("nop\n\t"); - } -} -#endif - -/* Initialize the system clock driver */ +/* Driver init: get first enabled timer from DT */ int sys_clock_driver_init(void) { /* connect the timer1 isr to the interrupt. The interrupt number @@ -223,7 +223,7 @@ int sys_clock_driver_init(void) * Every interrupt will reload the period register with the * next interrupt tick count */ - configure_timer1(); + initialize_timer(); irq_enable(DT_INST_IRQN(0)); return 0; } diff --git a/dts/bindings/timer/microchip,dspic33-timer.yaml b/dts/bindings/timer/microchip,dspic33-timer.yaml index e2029a20c5189..b6f3c885e61c4 100644 --- a/dts/bindings/timer/microchip,dspic33-timer.yaml +++ b/dts/bindings/timer/microchip,dspic33-timer.yaml @@ -15,7 +15,7 @@ properties: type: int required: true - prescalar: + prescaler: type: int required: true diff --git a/dts/dspic/p33ak128mc106.dtsi b/dts/dspic/p33ak128mc106.dtsi index 6f7a5a8bb5f30..b609e990d10f3 100644 --- a/dts/dspic/p33ak128mc106.dtsi +++ b/dts/dspic/p33ak128mc106.dtsi @@ -49,7 +49,7 @@ sram0: memory@4000 { compatible = "zephyr,memory"; - reg = <0x4000 0x20000>; + reg = <0x4000 0x4000>; label = "SRAM"; }; @@ -67,7 +67,7 @@ compatible = "microchip,dspic33-timer"; reg = <0x1E00 0xC>; clock-frequency = <4000000>; - prescalar = <8>; + prescaler = <8>; interrupt-parent = <&intc0>; interrupts = <48 1>; label = "TIMER_1"; diff --git a/dts/dspic/p33ak512mps512.dtsi b/dts/dspic/p33ak512mps512.dtsi index 4a8443e93b7b8..e6b5ed086c44a 100644 --- a/dts/dspic/p33ak512mps512.dtsi +++ b/dts/dspic/p33ak512mps512.dtsi @@ -66,7 +66,7 @@ compatible = "microchip,dspic33-timer"; reg = <0x1CE0 0xC>; clock-frequency = <4000000>; - prescalar = <8>; + prescaler = <8>; interrupt-parent = <&intc0>; interrupts = <48 1>; label = "TIMER_1"; diff --git a/include/zephyr/toolchain/xcdsc.h b/include/zephyr/toolchain/xcdsc.h index 26b161215f772..853d35710067f 100644 --- a/include/zephyr/toolchain/xcdsc.h +++ b/include/zephyr/toolchain/xcdsc.h @@ -237,17 +237,22 @@ static inline int popcount(unsigned int x) #define __GENERIC_DOT_SECTION(segment) __attribute__((section("." STRINGIFY(segment)))) #define Z_GENERIC_DOT_SECTION(segment) __GENERIC_DOT_SECTION(segment) -#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_XSDSC_H_ */ +#define ALIAS_OF(of) __attribute__((alias(#of))) -/* Double indirection to ensure section names are expanded before - * stringification - */ -#define __GENERIC_SECTION(segment) __attribute__((section(STRINGIFY(segment)))) -#define Z_GENERIC_SECTION(segment) __GENERIC_SECTION(segment) +#define FUNC_ALIAS(real_func, new_alias, return_type) return_type new_alias() ALIAS_OF(real_func) -#define __GENERIC_DOT_SECTION(segment) __attribute__((section("." STRINGIFY(segment)))) -#define Z_GENERIC_DOT_SECTION(segment) __GENERIC_DOT_SECTION(segment) +#if defined(_ASMLANGUAGE) -#define ALIAS_OF(of) __attribute__((alias(#of))) +.macro func_section sect sym + .section .§&.&sym&, keep, code, keep + .align 4 + .type _&sym&, @function +_&sym&: +.endm -#define FUNC_ALIAS(real_func, new_alias, return_type) return_type new_alias() ALIAS_OF(real_func) +#define GTEXT(sym) .global _##sym +#define SECTION_FUNC(sect, sym) func_section sect sym + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_XSDSC_H_ */ diff --git a/samples/basic/blinky/prj.conf b/samples/basic/blinky/prj.conf index fe2e63c01ec01..969277e35be2f 100644 --- a/samples/basic/blinky/prj.conf +++ b/samples/basic/blinky/prj.conf @@ -1,5 +1,4 @@ CONFIG_GPIO=y CONFIG_PRINTK=y CONFIG_RAM_CONSOLE=y -CONFIG_GPIO_DSPIC=y CONFIG_STATIC_INIT_GNU=y diff --git a/soc/microchip/dspic33/dspic33a/Kconfig.soc b/soc/microchip/dspic33/dspic33a/Kconfig.soc index ce681e7832048..916c8e36c1b11 100644 --- a/soc/microchip/dspic33/dspic33a/Kconfig.soc +++ b/soc/microchip/dspic33/dspic33a/Kconfig.soc @@ -25,5 +25,4 @@ config SOC_P33AK256MC506 config SOC default "p33ak128mc106" if SOC_P33AK128MC106 - default "p33ak256mc506" if SOC_P33AK256MC506 default "p33ak512mps512" if SOC_P33AK512MPS512 diff --git a/soc/microchip/dspic33/soc.yml b/soc/microchip/dspic33/soc.yml index 560781a1dafe8..16b5c9332e3fe 100644 --- a/soc/microchip/dspic33/soc.yml +++ b/soc/microchip/dspic33/soc.yml @@ -5,4 +5,3 @@ family: socs: - name: p33ak512mps512 - name: p33ak128mc106 - - name: p33ak256mc506 diff --git a/tests/kernel/mem_protect/stack_random/testcase.yaml b/tests/kernel/mem_protect/stack_random/testcase.yaml index b809f2875b9ef..57a52dcc2b767 100644 --- a/tests/kernel/mem_protect/stack_random/testcase.yaml +++ b/tests/kernel/mem_protect/stack_random/testcase.yaml @@ -2,6 +2,7 @@ tests: kernel.memory_protection.stack_random: arch_exclude: - posix + - dspic tags: - kernel - memory_protection diff --git a/tests/kernel/mem_protect/stackprot/src/main.c b/tests/kernel/mem_protect/stackprot/src/main.c index caf328a9ae1f4..ced761eba69b0 100644 --- a/tests/kernel/mem_protect/stackprot/src/main.c +++ b/tests/kernel/mem_protect/stackprot/src/main.c @@ -139,6 +139,14 @@ ZTEST_USER(stackprot, test_stackprot) */ ZTEST(stackprot, test_create_alt_thread) { + /** + * Since for the DSPIC the stack is growing upwards this test is not supported + * Skip this test to avoid failures. + */ +#ifdef CONFIG_DSPIC + ztest_test_skip(); +#endif + /* Start thread */ k_thread_create(&alt_thread_data, alt_thread_stack_area, STACKSIZE, alternate_thread, NULL, NULL, NULL,