Skip to content

Commit 098e304

Browse files
author
Vehicle Researcher
committed
Squashed 'panda/' changes from 98f29a4..67d5208
67d5208 fix signedness issue in toyota safety fe15d3f bump pandacan 11c2b08 add fault invalid 2c26e45 add sleep 27c7637 forgot the counter 3a6d7db don't hang bfa7d2e canloader works b259e2a can flasher is close to working 83f2edf isotp can support in softloader 7ae7c79 typo e85cc47 forgot the selfs 190b4f6 start work on canflasher 5c655c9 add recover support ae3457f usbflash is reliable f7a0ab0 pedal usbflash works 585d0f9 add way to call isotp be82899 despite it being bad code, move isotp 000715b start work on pedal canloader 626e312 pedal has a bootstub now 3662d1e redundant check 81e6b0d fix bug 083cd12 should have bounty to refactor that ish b65d30c bad asserts b2e6c3f isotp untested support for subaddr 30fd66a Merge pull request #93 from vntarasov/volt 06f5109 Merge pull request #94 from gregjhogan/can-printer-hex c7d098c Merge pull request #95 from gregjhogan/setup-script 22fe250 Merge pull request #99 from gregjhogan/bit-transition-example ba16ba3 Merge pull request #100 from gregjhogan/j2534-troubleshooting-instructions ad08ea4 Merge pull request #90 from gregjhogan/can-forwarding f3b6f5d added j2534 troubleshooting instructions 858d150 added script to find bits that transition from 0 to 1 c6acac8 added checking pedal interceptor message length f7226ff added brake safety checks d0c2634 added gas safety checks d378e4a removed bosch safety forwarding restriction on 29 bit addresses 5c7ef9e added bosch safety hooks and forwarding 90c64b6 add note 23de8d4 Merge pull request #97 from commaai/pedal_improvements 0261641 added missing python packages b92b235 fix bytearray encode issue 2434f1c Tweak Volt's brake pedal stickiness e2f73d2 enable has a whole byte to itself d5a9e1e correct checksum f8ed9fa better names 986a14c don't alias pointers 9b8472e add watchdog support 8f0add9 handle faults 1d917f8 split gas set into 2 values, and have a fault state 1b77026 j2534 isn't alpha anymore fbcc872 Merge pull request #92 from commaai/pedal 8a6f44b pedal is sending messages 08f464c python 3 bro is bad bro 9390961 kline checksum algo was broken... 3b7c33b add kline debug support aa622bc init values 631ea9f better refactor eb1fd75 add PEDAL adc sets ccaa310 don't build with usb 8d4d763 debug console works bd09883 comma pedal is building 75a29d5 Merge pull request #84 from gregjhogan/j2534-hds eece37d only the panda has gmlan 9f43abe Merge pull request #89 from vntarasov/volt 5364d43 Merge pull request #88 from vntarasov/smaller-firmware 377a1ec bump version for descriptor fix 4fabdf0 Merge pull request #87 from gregjhogan/usb-multi-packet-control 8580773 fix sending WinUSB Extended Properties Feature Descriptor 6908feb Chevy Volt safety 786a004 Enable optimization to reduce firmware size d70f43b hack to fix thinkpad 95ab1ae fixed flow control message padding bbd04d1 updated installer 62216d0 single standalone DLL for J2534 driver 5c9138d fixed 11 bit address issue f3b0ad2 fix LOOPBACK getting set when DATA_RATE is set b750d36 updated README a9a097f lowered CPU utilization 7c26a70 TIS needs unsupported protocols to return an error 42692b4 TIS doesn't like ChannelID being zero cf126bb SET_CONFIG return error for reserved parameters 2e99dbf fix HDS issues 8203cc8 add is_grey e946a54 add insecure_okay flag 4363b3e check webpage 4f59ded add secure mode note 6b11fb5 add autosecuring to tests b27d185 Merge pull request #86 from commaai/better_pairing 4b53b42 elm wifi isn't an automated test 99f85cb Merge pull request #85 from gregjhogan/usb-wcid 0d38060 auto-install WinUSB device driver c6653ca from python import 38cc0ee add wifi_secure_mode, boots in insecure mode git-subtree-dir: panda git-subtree-split: 67d5208
1 parent db67cff commit 098e304

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2044
-575
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ As a universal car interface, it should support every reasonable software interf
4545
- User space ([done](https://github.com/commaai/panda/tree/master/python))
4646
- socketcan in kernel ([alpha](https://github.com/commaai/panda/tree/master/drivers/linux))
4747
- ELM327 ([done](https://github.com/commaai/panda/blob/master/boardesp/elm327.c))
48-
- Windows J2534 ([alpha](https://github.com/commaai/panda/tree/master/drivers/windows))
48+
- Windows J2534 ([done](https://github.com/commaai/panda/tree/master/drivers/windows))
4949

5050
Directory structure
5151
------

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.0.7
1+
v1.0.9

board/bootstub.c

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
#include "drivers/usb.h"
2525
//#include "drivers/uart.h"
2626

27+
#ifdef PEDAL
28+
#define CUSTOM_CAN_INTERRUPTS
29+
#include "safety.h"
30+
#include "drivers/can.h"
31+
#endif
32+
2733
int puts(const char *a) { return 0; }
2834
void puth(unsigned int i) {}
2935

board/build.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -O0
1+
CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -O2
22
CFLAGS += -Tstm32_flash.ld
33

44
CC = arm-none-eabi-gcc

board/drivers/can.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ void can_init_all() {
199199
}
200200

201201
void can_set_gmlan(int bus) {
202+
#ifdef PANDA
202203
if (bus == -1 || bus != can_num_lookup[3]) {
203204
// GMLAN OFF
204205
switch (can_num_lookup[3]) {
@@ -238,6 +239,7 @@ void can_set_gmlan(int bus) {
238239
can_num_lookup[3] = 2;
239240
can_init(2);
240241
}
242+
#endif
241243
}
242244

243245
// CAN error
@@ -346,13 +348,14 @@ void can_rx(uint8_t can_number) {
346348

347349
// forwarding (panda only)
348350
#ifdef PANDA
349-
if (can_forwarding[bus_number] != -1) {
351+
int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
352+
if (bus_fwd_num != -1) {
350353
CAN_FIFOMailBox_TypeDef to_send;
351354
to_send.RIR = to_push.RIR | 1; // TXRQ
352355
to_send.RDTR = to_push.RDTR;
353356
to_send.RDLR = to_push.RDLR;
354357
to_send.RDHR = to_push.RDHR;
355-
can_send(&to_send, can_forwarding[bus_number]);
358+
can_send(&to_send, bus_fwd_num);
356359
}
357360
#endif
358361

@@ -370,6 +373,8 @@ void can_rx(uint8_t can_number) {
370373
}
371374
}
372375

376+
#ifndef CUSTOM_CAN_INTERRUPTS
377+
373378
void CAN1_TX_IRQHandler() { process_can(0); }
374379
void CAN1_RX0_IRQHandler() { can_rx(0); }
375380
void CAN1_SCE_IRQHandler() { can_sce(CAN1); }
@@ -384,6 +389,8 @@ void CAN3_RX0_IRQHandler() { can_rx(2); }
384389
void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
385390
#endif
386391

392+
#endif
393+
387394
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
388395
if (safety_tx_hook(to_push)) {
389396
if (bus_number < BUS_MAX) {

board/drivers/drivers.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ uint32_t adc_get(int channel);
8888
// ********************* DAC *********************
8989

9090
void dac_init();
91-
uint32_t dac_set(int channel, uint32_t value);
91+
void dac_set(int channel, uint32_t value);
9292

9393

9494
// ********************* TIMER *********************

board/drivers/usb.h

+101-1
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,15 @@ uint8_t resp[MAX_RESP_LEN];
7171
#define ENDPOINT_TYPE_BULK 2
7272
#define ENDPOINT_TYPE_INT 3
7373

74+
// This is an arbitrary value used in bRequest
75+
#define MS_VENDOR_CODE 0x20
76+
7477
//Convert machine byte order to USB byte order
7578
#define TOUSBORDER(num)\
7679
(num&0xFF), ((num>>8)&0xFF)
7780

7881
uint8_t device_desc[] = {
79-
DSCR_DEVICE_LEN, DSCR_DEVICE_TYPE, 0x00, 0x01, //Length, Type, bcdUSB
82+
DSCR_DEVICE_LEN, DSCR_DEVICE_TYPE, 0x00, 0x02, //Length, Type, bcdUSB
8083
0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size
8184
TOUSBORDER(USB_VID), // idVendor
8285
TOUSBORDER(USB_PID), // idProduct
@@ -165,9 +168,47 @@ uint16_t string_3_desc[] = {
165168
'n', 'o', 'n', 'e'
166169
};
167170

171+
#ifdef PANDA
172+
// WCID (auto install WinUSB driver)
173+
// https://github.com/pbatard/libwdi/wiki/WCID-Devices
174+
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file
175+
uint8_t string_238_desc[] = {
176+
0x12, 0x03, // bLength, bDescriptorType
177+
'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100)
178+
MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad
179+
};
180+
uint8_t winusb_ext_compatid_os_desc[] = {
181+
0x28, 0x00, 0x00, 0x00, // dwLength
182+
0x00, 0x01, // bcdVersion
183+
0x04, 0x00, // wIndex
184+
0x01, // bCount
185+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved
186+
0x00, // bFirstInterfaceNumber
187+
0x00, // Reserved
188+
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB)
189+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none)
190+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved
191+
};
192+
uint8_t winusb_ext_prop_os_desc[] = {
193+
0x8e, 0x00, 0x00, 0x00, // dwLength
194+
0x00, 0x01, // bcdVersion
195+
0x05, 0x00, // wIndex
196+
0x01, 0x00, // wCount
197+
// first property
198+
0x84, 0x00, 0x00, 0x00, // dwSize
199+
0x01, 0x00, 0x00, 0x00, // dwPropertyDataType
200+
0x28, 0x00, // wPropertyNameLength
201+
'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID)
202+
0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength
203+
'{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9})
204+
};
205+
#endif
206+
168207
// current packet
169208
USB_Setup_TypeDef setup;
170209
uint8_t usbdata[0x100];
210+
uint8_t* ep0_txdata = NULL;
211+
uint16_t ep0_txlen = 0;
171212

172213
// Store the current interface alt setting.
173214
int current_int0_alt_setting = 0;
@@ -206,6 +247,26 @@ void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) {
206247
}
207248
}
208249

250+
// IN EP 0 TX FIFO has a max size of 127 bytes (much smaller than the rest)
251+
// so use TX FIFO empty interrupt to send larger amounts of data
252+
void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
253+
#ifdef DEBUG_USB
254+
puts("writing ");
255+
hexdump(src, len);
256+
#endif
257+
258+
uint16_t wplen = min(len, 0x40);
259+
USB_WritePacket(src, wplen, 0);
260+
261+
if (wplen < len) {
262+
ep0_txdata = src + wplen;
263+
ep0_txlen = len - wplen;
264+
USBx_DEVICE->DIEPEMPMSK |= 1;
265+
} else {
266+
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
267+
}
268+
}
269+
209270
void usb_reset() {
210271
// unmask endpoint interrupts, so many sets
211272
USBx_DEVICE->DAINT = 0xFFFFFFFF;
@@ -345,6 +406,11 @@ void usb_setup() {
345406
USB_WritePacket((const uint8_t *)string_3_desc, min(sizeof(string_3_desc), setup.b.wLength.w), 0);
346407
#endif
347408
break;
409+
#ifdef PANDA
410+
case 238:
411+
USB_WritePacket((uint8_t*)string_238_desc, min(sizeof(string_238_desc), setup.b.wLength.w), 0);
412+
break;
413+
#endif
348414
default:
349415
// nothing
350416
USB_WritePacket(0, 0, 0);
@@ -372,6 +438,22 @@ void usb_setup() {
372438
USB_WritePacket(0, 0, 0);
373439
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
374440
break;
441+
#ifdef PANDA
442+
case MS_VENDOR_CODE:
443+
switch (setup.b.wIndex.w) {
444+
// Extended Compat ID OS Descriptor
445+
case 4:
446+
USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, min(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w));
447+
break;
448+
// Extended Properties OS Descriptor
449+
case 5:
450+
USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, min(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w));
451+
break;
452+
default:
453+
USB_WritePacket_EP0(0, 0);
454+
}
455+
break;
456+
#endif
375457
default:
376458
resp_len = usb_cb_control_msg(&setup, resp, 1);
377459
USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0);
@@ -682,6 +764,24 @@ void usb_irqhandler(void) {
682764
break;
683765
}
684766

767+
if (USBx_INEP(0)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
768+
#ifdef DEBUG_USB
769+
puts(" IN PACKET QUEUE\n");
770+
#endif
771+
772+
if (ep0_txlen != 0 && (USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40) {
773+
uint16_t len = min(ep0_txlen, 0x40);
774+
USB_WritePacket(ep0_txdata, len, 0);
775+
ep0_txdata += len;
776+
ep0_txlen -= len;
777+
if (ep0_txlen == 0) {
778+
ep0_txdata = NULL;
779+
USBx_DEVICE->DIEPEMPMSK &= ~1;
780+
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
781+
}
782+
}
783+
}
784+
685785
// clear interrupts
686786
USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT; // Why ep0?
687787
USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT;

board/get_sdk.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#!/bin/bash
22
sudo apt-get install gcc-arm-none-eabi python-pip
3-
sudo pip2 install libusb1
3+
sudo pip2 install libusb1 pycrypto requests

board/get_sdk_mac.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
# Need formula for gcc
33
brew tap ArmMbed/homebrew-formulae
44
brew install python dfu-util arm-none-eabi-gcc
5-
pip2 install libusb1
5+
pip2 install libusb1 pycrypto requests

board/gpio.h

+26-5
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,15 @@ void clock_init() {
7272
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
7373
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
7474
#else
75-
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
76-
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
75+
#ifdef PEDAL
76+
// comma pedal has a 16mhz crystal
77+
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
78+
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
79+
#else
80+
// NEO board has a 8mhz crystal
81+
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
82+
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
83+
#endif
7784
#endif
7885

7986
// start PLL
@@ -132,8 +139,13 @@ void set_can_enable(CAN_TypeDef *CAN, int enabled) {
132139
// CAN1_EN
133140
set_gpio_output(GPIOC, 1, !enabled);
134141
#else
135-
// CAN1_EN
136-
set_gpio_output(GPIOB, 3, enabled);
142+
#ifdef PEDAL
143+
// CAN1_EN (not flipped)
144+
set_gpio_output(GPIOB, 3, !enabled);
145+
#else
146+
// CAN1_EN
147+
set_gpio_output(GPIOB, 3, enabled);
148+
#endif
137149
#endif
138150
} else if (CAN == CAN2) {
139151
#ifdef PANDA
@@ -285,6 +297,14 @@ void gpio_init() {
285297
set_gpio_mode(GPIOC, 2, MODE_ANALOG);
286298
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
287299

300+
#ifdef PEDAL
301+
// comma pedal has inputs on C0 and C1
302+
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
303+
set_gpio_mode(GPIOC, 1, MODE_ANALOG);
304+
// DAC outputs on A4 and A5
305+
// apparently they don't need GPIO setup
306+
#endif
307+
288308
// C8: FAN aka TIM3_CH4
289309
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);
290310

@@ -443,9 +463,10 @@ void early() {
443463

444464

445465
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
466+
#ifdef PANDA
446467
set_esp_mode(ESP_DISABLED);
468+
#endif
447469
set_led(LED_GREEN, 1);
448-
449470
jump_to_bootloader();
450471
}
451472

board/pedal/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
obj/*

board/pedal/Makefile

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# :set noet
2+
PROJ_NAME = comma
3+
4+
CFLAGS = -O2 -Wall -std=gnu11 -DPEDAL
5+
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
6+
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
7+
CFLAGS += -I ../inc -I ../ -I ../../ -nostdlib
8+
CFLAGS += -T../stm32_flash.ld
9+
10+
STARTUP_FILE = startup_stm32f205xx
11+
12+
CC = arm-none-eabi-gcc
13+
OBJCOPY = arm-none-eabi-objcopy
14+
OBJDUMP = arm-none-eabi-objdump
15+
DFU_UTIL = "dfu-util"
16+
17+
# pedal only uses the debug cert
18+
CERT = ../../certs/debug
19+
CFLAGS += "-DALLOW_DEBUG"
20+
21+
canflash: obj/$(PROJ_NAME).bin
22+
../../tests/pedal/enter_canloader.py $<
23+
24+
usbflash: obj/$(PROJ_NAME).bin
25+
../../tests/pedal/enter_canloader.py; sleep 0.5
26+
PYTHONPATH=../../ python -c "from python import Panda; p = [x for x in [Panda(x) for x in Panda.list()] if x.bootstub]; assert(len(p)==1); p[0].flash('obj/$(PROJ_NAME).bin', reconnect=False)"
27+
28+
recover: obj/bootstub.bin obj/$(PROJ_NAME).bin
29+
../../tests/pedal/enter_canloader.py --recover; sleep 0.5
30+
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
31+
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.bin
32+
33+
obj/main.o: main.c ../*.h
34+
mkdir -p obj
35+
$(CC) $(CFLAGS) -o $@ -c $<
36+
37+
obj/bootstub.o: ../bootstub.c ../*.h
38+
mkdir -p obj
39+
$(CC) $(CFLAGS) -o $@ -c $<
40+
41+
obj/$(STARTUP_FILE).o: ../$(STARTUP_FILE).s
42+
$(CC) $(CFLAGS) -o $@ -c $<
43+
44+
obj/%.o: ../../crypto/%.c
45+
$(CC) $(CFLAGS) -o $@ -c $<
46+
47+
obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.o
48+
# hack
49+
$(CC) -Wl,--section-start,.isr_vector=0x8004000 $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
50+
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf obj/code.bin
51+
SETLEN=1 ../../crypto/sign.py obj/code.bin $@ $(CERT)
52+
53+
obj/bootstub.bin: obj/$(STARTUP_FILE).o obj/bootstub.o obj/sha.o obj/rsa.o
54+
$(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^
55+
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@
56+
57+
clean:
58+
rm -f obj/*
59+

0 commit comments

Comments
 (0)