-
Notifications
You must be signed in to change notification settings - Fork 47
Add PIC32MZ EF bare-metal wolfIP port: clocks, UART2, wolfCrypt RNG, LAN8740 PHY #140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # Build artifacts | ||
| *.o | ||
| app.elf | ||
| app.hex | ||
| app.map | ||
| # MDB / IPE transient files | ||
| mdb_flash.cmd | ||
| MPLABXLog.* | ||
| log.* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # wolfIP PIC32MZ EF port - build with Microchip XC32 | ||
| # | ||
| # Copyright (C) 2026 wolfSSL Inc. Part of the wolfIP TCP/IP stack (GPLv3). | ||
| # | ||
| # Phase 0: clocks + UART2 console + heartbeat. | ||
| # Phase 1: wolfCrypt PIC32MZ hardware TRNG self-test. | ||
| # Phase 2: MDIO + LAN8740 PHY link bring-up. | ||
| # (Full Ethernet RX/TX driver + wolfIP core are added in later phases.) | ||
| # | ||
| # Usage: | ||
| # make # build app.hex | ||
| # make flash # program over the on-board debugger (v6.20 IPE) | ||
| # make clean | ||
| # Overridable: | ||
| # XC32_BIN= XC32 bin dir (default /opt/microchip/xc32/v5.10/bin) | ||
| # DFP= device family pack version dir | ||
| # DEVICE= 32MZ2048EFM144 | ||
| # WOLFSSL_ROOT= path to wolfssl checkout (used from Phase 1 on) | ||
| # MDB= MPLAB X MDB CLI (default v6.20; v6.30 dropped the EF SK debugger) | ||
|
|
||
| XC32_BIN ?= /opt/microchip/xc32/v5.10/bin | ||
| DFP ?= /opt/microchip/mplabx/v6.30/packs/Microchip/PIC32MZ-EF_DFP/1.5.173 | ||
| DEVICE ?= 32MZ2048EFM144 | ||
|
|
||
| CC := $(XC32_BIN)/xc32-gcc | ||
| BIN2HEX := $(XC32_BIN)/xc32-bin2hex | ||
| SIZE := $(XC32_BIN)/xc32-size | ||
|
|
||
| # Flashing via MDB (Microchip DeBugger CLI). The headless ipecmd cannot resolve | ||
| # device packs ("Unable to locate DFP"), but MDB launches the full platform and | ||
| # resolves them like the IDE/IPE GUI does. Default tool is an MPLAB ICD 5 on the | ||
| # ICSP header; the EF Starter Kit's flaky on-board debugger (MDB tool type "sk", | ||
| # only in v6.20) proved unreliable over USB, so an external debugger is preferred. | ||
| MDB ?= /opt/microchip/mplabx/v6.30/mplab_platform/bin/mdb.sh | ||
| MDB_DEVICE ?= PIC32MZ2048EFM144 | ||
| MDB_TOOL ?= icd5 | ||
|
|
||
| ROOT := ../../.. | ||
| # Default to a wolfssl checkout sitting beside the wolfip repo. | ||
| WOLFSSL_ROOT ?= $(ROOT)/../wolfssl | ||
|
|
||
| # -O1 is available in the free XC32 edition (-O2/-Os/-O3 need a PRO license). | ||
| CFLAGS := -mprocessor=$(DEVICE) -mdfp="$(DFP)" | ||
| CFLAGS += -O1 -g -Wall -Wextra -ffunction-sections -fdata-sections | ||
| CFLAGS += -I. -I$(ROOT) -I$(ROOT)/src | ||
| CFLAGS += -DWOLFSSL_USER_SETTINGS -I$(WOLFSSL_ROOT) | ||
| CFLAGS += $(EXTRA_CFLAGS) | ||
|
|
||
| # Heap for the Hash-DRBG (wc_InitRng allocates the DRBG state). | ||
| LDFLAGS := -mprocessor=$(DEVICE) -mdfp="$(DFP)" | ||
| LDFLAGS += -Wl,--defsym,_min_heap_size=0x8000 | ||
| LDFLAGS += -Wl,--gc-sections -Wl,-Map=app.map,--cref | ||
|
|
||
| # Port + application sources (strict warnings) | ||
| APP_SRCS := device_config.c clock_init.c uart_console.c timebase.c \ | ||
| wolf_compat.c rng_selftest.c pic32mz_eth.c phy_lan8740.c main.c | ||
| APP_OBJS := $(patsubst %.c,%.o,$(APP_SRCS)) | ||
|
|
||
| # wolfcrypt sources for the RNG self-test (compiled with relaxed warnings). | ||
| # Pulled directly from the sibling wolfssl checkout, no copy. | ||
| WC_SRC := $(WOLFSSL_ROOT)/wolfcrypt/src | ||
| WC_NAMES := random sha256 hash wc_port logging memory error | ||
| WC_OBJS := $(addsuffix .o,$(addprefix wc_,$(WC_NAMES))) | ||
| CFLAGS_WC := -mprocessor=$(DEVICE) -mdfp="$(DFP)" -O1 -g \ | ||
| -ffunction-sections -fdata-sections \ | ||
| -DWOLFSSL_USER_SETTINGS -I. -I$(WOLFSSL_ROOT) | ||
|
|
||
| # wolfIP core stack (relaxed warnings; does not need wolfssl). | ||
| CFLAGS_CORE := -mprocessor=$(DEVICE) -mdfp="$(DFP)" -O1 -g \ | ||
| -ffunction-sections -fdata-sections -I. -I$(ROOT) -I$(ROOT)/src | ||
|
|
||
| ALL_OBJS := $(APP_OBJS) wolfip.o $(WC_OBJS) | ||
|
|
||
| all: app.hex | ||
| @echo "Built PIC32MZ wolfIP port" | ||
| @$(SIZE) app.elf | ||
|
|
||
| app.elf: $(ALL_OBJS) | ||
| $(CC) $(CFLAGS) $(ALL_OBJS) $(LDFLAGS) -o $@ | ||
|
|
||
| app.hex: app.elf | ||
| $(BIN2HEX) $< | ||
|
|
||
| %.o: %.c | ||
| $(CC) $(CFLAGS) -c $< -o $@ | ||
|
|
||
| wc_%.o: $(WC_SRC)/%.c | ||
| $(CC) $(CFLAGS_WC) -c $< -o $@ | ||
|
|
||
| wolfip.o: $(ROOT)/src/wolfip.c | ||
| $(CC) $(CFLAGS_CORE) -c $< -o $@ | ||
|
|
||
| # Program the hex over an MPLAB ICD 5 (on the ICSP/debug header) via MDB. Close | ||
| # the MPLAB X IPE/IDE GUI first so it isn't holding the tool. Command script: | ||
| # set programoptions.eraseb4program true -> full chip erase before program | ||
| # hwtool icd5 -p -> connect the ICD 5 for programming | ||
| # program <app.hex> / Reset -> program, then release from reset | ||
| # The trailing "Reset" is required: -p alone leaves the target held in reset. | ||
| # The ICD 5 connects to the target's ICSP/debug header; select a different | ||
| # supported tool with MDB_TOOL= (e.g. icd4, pickit4, snap). See Microchip's | ||
| # MPLAB ICD 5 User's Guide for connection and wiring details. | ||
| flash: app.hex | ||
| @printf 'device %s\nset programoptions.eraseb4program true\nhwtool %s -p\nprogram %s\nReset\nquit\n' \ | ||
| "$(MDB_DEVICE)" "$(MDB_TOOL)" "$(CURDIR)/app.hex" > mdb_flash.cmd | ||
| cd $(dir $(MDB)) && sh ./$(notdir $(MDB)) $(CURDIR)/mdb_flash.cmd | ||
|
|
||
| clean: | ||
| rm -f *.o app.elf app.hex app.map mdb_flash.cmd MPLABXLog.* log.* | ||
|
|
||
| .PHONY: all clean flash | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| # wolfIP PIC32MZ EF Port | ||
|
|
||
| Bare-metal [wolfIP](../../../README.md) port for the **Microchip PIC32MZ EF** | ||
| (PIC32MZ2048EFM144, MIPS32 M-class) with a **LAN8740** PHY over RMII. Built | ||
| with the Microchip XC32 toolchain; no MPLAB X project or Harmony framework | ||
| required. Also exercises wolfCrypt's built-in hardware TRNG | ||
| (`WOLFSSL_PIC32MZ_RNG`). | ||
|
|
||
| ## Hardware | ||
|
|
||
| - **MCU:** PIC32MZ2048EFM144 (200 MHz, 2 MB flash, 512 KB RAM), EF Starter Kit. | ||
| - **PHY:** LAN8740 daughter board over RMII (PHY drives the 50 MHz reference clock). | ||
| - **Console:** UART2, `U2TX` on RPB14 / `U2RX` on RPG6, 115200 8N1. | ||
| - **Programmer:** MPLAB ICD 5 on the ICSP/debug header; program with `make flash` (see the Makefile `flash` target, which drives the ICD 5 over MDB). | ||
|
|
||
| ## Layout | ||
|
|
||
| | File | Purpose | | ||
| |------|---------| | ||
| | `device_config.c` | DEVCFG config words: 200 MHz PLL (POSC EC 24 MHz), RMII, watchdog off. | | ||
| | `clock_init.c/.h` | Flash wait-states + prefetch. Reusable early bring-up (wolfBoot). | | ||
| | `cache.h` | MIPS KSEG0/KSEG1 + virtual/physical helpers for DMA memory. | | ||
| | `uart_console.c/.h` | UART2 console + XC32 `_mon_putc` `printf` retarget. | | ||
| | `timebase.c/.h` | 64-bit `millis()` from the CP0 core timer. | | ||
| | `pic32mz_eth.c/.h` | EMAC + RMII + MDIO bring-up, DMA descriptor rings, `poll`/`send`. | | ||
| | `phy_lan8740.c/.h` | MAC-agnostic clause-22 LAN8740 driver (scan, autoneg, link). | | ||
| | `rng_selftest.c/.h` | wolfCrypt hardware-TRNG self-test. | | ||
| | `user_settings.h` | wolfCrypt configuration (`WOLFSSL_MICROCHIP_PIC32MZ`). | | ||
| | `config.h` | wolfIP profile (MTU, socket counts, DHCP). | | ||
| | `main.c` | TRNG self-test, DHCP, and a TCP echo / throughput server. | | ||
|
|
||
| ## Build | ||
|
|
||
| Requires XC32 (>= v5.10) and the PIC32MZ-EF DFP, plus a wolfssl checkout beside | ||
| the wolfip repo (override with `WOLFSSL_ROOT=`). | ||
|
|
||
| ```sh | ||
| make # -> app.hex | ||
| make SPEED_TEST=1 EXTRA_CFLAGS=-DSPEED_TEST # throughput server on port 9 | ||
| make flash # program over MPLAB ICD 5 (MDB) | ||
| make clean | ||
| ``` | ||
|
|
||
| Overridable: `XC32_BIN`, `DFP`, `DEVICE`, `WOLFSSL_ROOT`, `MDB`, `MDB_TOOL`. | ||
|
|
||
| ## Test | ||
|
|
||
| Console at 115200 8N1. On boot the firmware prints the banner, the RNG | ||
| self-test result, the resolved PHY link, and (once bound) the DHCP address: | ||
|
|
||
| ``` | ||
| === wolfIP PIC32MZ EF port === | ||
| [RNG] self-test: PASS | ||
| Ethernet init (LAN8740 over RMII)... | ||
| DHCP bound: 10.0.4.x | ||
| TCP service listening on port 7 | ||
| ``` | ||
|
|
||
| Then, from a host on the same network: | ||
|
|
||
| ```sh | ||
| ping <ip> | ||
| echo hello | nc <ip> 7 # echo (default build) | ||
| dd if=/dev/zero bs=1460 count=700 | nc <ip> 9 # RX throughput (SPEED_TEST build) | ||
| nc <ip> 9 </dev/null | pv >/dev/null # TX throughput (SPEED_TEST build) | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - DMA descriptors/buffers use XC32 `__attribute__((coherent))` (uncached), so | ||
| no cache maintenance is needed; the EMAC is given physical addresses. | ||
| - The Ethernet module needs PBCLK5 enabled and `PMD6.ETHMD` cleared before any | ||
| EMAC register access — `pic32mz_emac_mii_init()` does this first. | ||
| - The PIC32 Ethernet DMA descriptor is 4 words (16 bytes): header, buffer | ||
| address, and two words the DMA writes back. The received frame length comes | ||
| from the status word (`status & 0xFFFF`), not the header. | ||
| - The echo server holds transfers in the per-socket buffers | ||
| (`RXBUF_SIZE`/`TXBUF_SIZE`), so a single burst larger than that will stall | ||
| the simple echo callback; raise the buffers or use the throughput server | ||
| (`-DSPEED_TEST`) for large streams. | ||
| - Build with `EXTRA_CFLAGS=-DPIC32_ETH_TRACE` to trace the EMAC bring-up. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /* board.h | ||
| * | ||
| * Board constants for the PIC32MZ EF Starter Kit (DM320007) + LAN8740 PHY DB. | ||
| * | ||
| * Copyright (C) 2026 wolfSSL Inc. | ||
| * | ||
| * This file is part of wolfIP TCP/IP stack. | ||
| * | ||
| * wolfIP is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * wolfIP is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program; if not, write to the Free Software | ||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA | ||
| */ | ||
| #ifndef PIC32MZ_BOARD_H | ||
| #define PIC32MZ_BOARD_H | ||
|
|
||
| /* Clock tree (set by DEVCFG config words at reset; see device_config.c) */ | ||
| #define SYS_CLK_FREQ 200000000ul /* SYSCLK from SPLL */ | ||
| #define PBCLK2_FREQ 100000000ul /* peripheral bus 2 (UART) = SYSCLK/2 */ | ||
| #define PBCLK5_FREQ 100000000ul /* peripheral bus 5 (EMAC) = SYSCLK/2 */ | ||
|
|
||
| /* Console UART: U2TX on RPB14, U2RX on RPG6 (external MCP2221 USB-UART) */ | ||
| #define CONSOLE_BAUD 115200u | ||
|
|
||
| /* On-board LEDs LED1/LED2/LED3 on RH0/RH1/RH2 (active high) */ | ||
| #define LED_MASK 0x0007u | ||
| #define LED_HEARTBEAT 0x0001u /* LED1 = RH0 */ | ||
|
|
||
| #endif /* PIC32MZ_BOARD_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* cache.h | ||
| * | ||
| * MIPS KSEG segment helpers for DMA-coherent access on PIC32MZ. | ||
| * | ||
| * Copyright (C) 2026 wolfSSL Inc. | ||
| * | ||
| * This file is part of wolfIP TCP/IP stack. | ||
| * | ||
| * wolfIP is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * wolfIP is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program; if not, write to the Free Software | ||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA | ||
| */ | ||
| #ifndef PIC32MZ_CACHE_H | ||
| #define PIC32MZ_CACHE_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| /* The PIC32MZ Ethernet controller (EMAC) is not cache-coherent and programs | ||
| * its descriptor base/buffer pointers with PHYSICAL addresses. The simplest | ||
| * coherent scheme on MIPS is to access all descriptor rings and DMA buffers | ||
| * through KSEG1 (uncached) virtual aliases and hand the EMAC the physical | ||
| * address. This avoids per-operation cache clean/invalidate entirely. | ||
| * | ||
| * Equivalent to XC32 <sys/kmem.h> KVA0_TO_KVA1 / KVA_TO_PA / PA_TO_KVA1, but | ||
| * kept self-contained so the early bare-metal layer can be lifted into | ||
| * wolfBoot without pulling in the XC32 system headers. | ||
| */ | ||
|
|
||
| /* Cached KSEG0 virtual address -> uncached KSEG1 virtual address */ | ||
| #define PIC32_KVA0_TO_KVA1(v) (((uint32_t)(v)) | 0x20000000u) | ||
|
|
||
| /* Any KSEG0/KSEG1 virtual address -> physical address (for the EMAC) */ | ||
| #define PIC32_KVA_TO_PA(v) (((uint32_t)(v)) & 0x1FFFFFFFu) | ||
|
|
||
| /* Physical address -> uncached KSEG1 virtual address */ | ||
| #define PIC32_PA_TO_KVA1(pa) (((uint32_t)(pa)) | 0xA0000000u) | ||
|
|
||
| /* Pointer helper: uncached view of a normally-allocated object */ | ||
| #define PIC32_UNCACHED(p) ((void *)PIC32_KVA0_TO_KVA1(p)) | ||
|
|
||
| #endif /* PIC32MZ_CACHE_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /* clock_init.c | ||
| * | ||
| * Copyright (C) 2026 wolfSSL Inc. | ||
| * | ||
| * This file is part of wolfIP TCP/IP stack. | ||
| * | ||
| * wolfIP is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * wolfIP is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program; if not, write to the Free Software | ||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA | ||
| */ | ||
| #include <xc.h> | ||
| #include "clock_init.h" | ||
|
|
||
| void clock_init(void) | ||
| { | ||
| /* Flash wait-states + prefetch for 200 MHz SYSCLK. | ||
| * PFMWS = 2 wait-states is required above ~134 MHz on PIC32MZ EF. | ||
| * PREFEN = 3 enables predictive prefetch for cacheable and | ||
| * non-cacheable regions. PRECON is not lock-protected. */ | ||
| PRECONbits.PFMWS = 2; | ||
| PRECONbits.PREFEN = 3; | ||
|
|
||
| /* Peripheral buses PBCLK2 (UART) and PBCLK5 (EMAC) remain at their | ||
| * reset default of SYSCLK/2 = 100 MHz, which is what this port targets. | ||
| * The L1 cache and KSEG0 coherency are enabled by the XC32 reset | ||
| * startup code, so nothing is done here for v1. */ | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* clock_init.h | ||
| * | ||
| * Copyright (C) 2026 wolfSSL Inc. | ||
| * | ||
| * This file is part of wolfIP TCP/IP stack. | ||
| * | ||
| * wolfIP is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * wolfIP is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program; if not, write to the Free Software | ||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA | ||
| */ | ||
| #ifndef PIC32MZ_CLOCK_INIT_H | ||
| #define PIC32MZ_CLOCK_INIT_H | ||
|
|
||
| /* Configure flash wait-states / prefetch for 200 MHz operation. | ||
| * The PLL itself is brought up at reset from the DEVCFG config words | ||
| * (FNOSC=SPLL), so by the time main() runs SYSCLK is already 200 MHz. | ||
| * Bare-metal reusable (intended to be lifted into a future wolfBoot port). */ | ||
| void clock_init(void); | ||
|
|
||
| #endif /* PIC32MZ_CLOCK_INIT_H */ |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.