├── .gitmodules ├── LICENSE ├── README.md ├── _config.yml └── raspberrypi ├── LICENSE ├── Makefile ├── arm_ex_handler_weak.c ├── arm_exceptions.c ├── arm_exceptions.h ├── bcm283x.h ├── bcm283x_aux.h ├── bcm283x_clockmgr.c ├── bcm283x_clockmgr.h ├── bcm283x_gpio.c ├── bcm283x_gpio.h ├── bcm283x_i2c.h ├── bcm283x_it.h ├── bcm283x_mailbox.c ├── bcm283x_mailbox.h ├── bcm283x_pwm.h ├── bcm283x_spi.h ├── bcm283x_systimer.h ├── bcm283x_uart.h ├── config-template.txt ├── fatfs_port.c ├── fs ├── README.txt ├── boot.py ├── lib │ ├── fbconsole.py │ ├── ramdisk.py │ └── rpi.py └── main.py ├── gccollect.c ├── gccollect.h ├── gchelper.s ├── gpu.c ├── gpu.h ├── gpu_vc_property.c ├── gpu_vc_property.h ├── i2c.c ├── i2c.h ├── kernel.ld ├── machine_clockmgr.c ├── machine_i2c.c ├── machine_pin.c ├── machine_pin_util.h ├── machine_pwm.c ├── machine_sdcard.c ├── machine_spi.c ├── machine_timer.c ├── machine_usb_mode.c ├── machine_usb_mode.h ├── main.c ├── mini-uart.c ├── mini-uart.h ├── modgpu.c ├── modmachine.c ├── modmachine.h ├── modmcu.c ├── moduos.c ├── modutime.c ├── mpconfigport.h ├── mpconfigport.mk ├── mphalport.c ├── mphalport.h ├── pwm.c ├── pwm.h ├── qstrdefsport.h ├── rpi.c ├── rpi.h ├── sd.c ├── sd.h ├── spi.c ├── spi.h ├── start.s ├── uart.c ├── uart.h ├── usbhost.c ├── usbhost.h ├── usbkbd.c ├── usbkbd.h ├── vc_property.c └── vc_property.h /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "micropython"] 2 | path = micropython 3 | url = https://github.com/micropython/micropython.git 4 | [submodule "raspberrypi/csud"] 5 | path = raspberrypi/csud 6 | url = https://github.com/boochow/csud 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # micropython-raspberrypi 2 | 3 | MicroPython on bare metal Raspberry Pi Zero / Zero W / 2 4 | 5 | ## How to build 6 | ``` 7 | git clone https://github.com/boochow/micropython-raspberrypi.git 8 | cd micropython-raspberrypi 9 | git submodule update --init 10 | cd micropython; git submodule update --init; cd .. 11 | cd raspberrypi 12 | ``` 13 | for Raspberry Pi Zero/Zero W, 14 | ``` 15 | make BOARD=RPI1 16 | ``` 17 | for Raspberry Pi 2 18 | ``` 19 | make BOARD=RPI2 20 | ``` 21 | ## Options 22 | 1. `MICROPY_HW_USBHOST=1` to enable USB keyboard support. 23 | 1. `MICROPY_MOUNT_SD_CARD=1` to mount SD card on /sd in the boot sequence(default). 24 | 25 | ## How to install 26 | 27 | 1. download `bootcode.bin` and `start.elf` from https://github.com/raspberrypi/firmware/tree/master/boot 28 | 1. copy `bootcode.bin` and `start.elf` to the root of your microSD card 29 | 1. copy `build/firmware.img` to the root of your microSD card 30 | 1. copy build/config.txt to the root of your microSD card. (if `config.txt` already exists, edit it to add a line `kernel=firmware.img`.) 31 | 32 | ## Modules and Classes 33 | 34 | See [wiki](https://github.com/boochow/micropython-raspberrypi/wiki). 35 | 36 | ## References 37 | 38 | The First bare metal Raspberry Pi port by Stefan Naumann. ([Bare\-Metal Raspberry Pi port by naums · Pull Request \#3522 · micropython/micropython](https://github.com/micropython/micropython/pull/3522)) 39 | 40 | csud USB host driver by Alex Chadwick. ([Chadderz121/csud: Chadderz's Simple USB Driver for Raspberry Pi](https://github.com/Chadderz121/csud) I modified this to support RPi zero/zero W. The modified version is [here](https://github.com/boochow/csud)). 41 | 42 | sd.c SD card driver by Zoltan Baldaszti. ([raspi3\-tutorial/0B\_readsector at master · bztsrc/raspi3\-tutorial](https://github.com/bztsrc/raspi3-tutorial/tree/master/0B_readsector)) 43 | 44 | A lot of bare metal examples by David Welch. ([dwelch67/raspberrypi: Raspberry Pi ARM based bare metal examples](https://github.com/dwelch67/raspberrypi)) -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /raspberrypi/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /raspberrypi/Makefile: -------------------------------------------------------------------------------- 1 | # BOARD: RPI1 or RPI2 2 | BOARD ?= RPI1 3 | 4 | include ../micropython/py/mkenv.mk 5 | include mpconfigport.mk 6 | 7 | # qstr definitions (must come before including py.mk) 8 | QSTR_DEFS = qstrdefsport.h 9 | 10 | FROZEN_DIR ?= scripts 11 | # FROZEN_MPY_DIR ?= modules 12 | 13 | # include py core make definitions 14 | include $(TOP)/py/py.mk 15 | 16 | CROSS_COMPILE = arm-none-eabi- 17 | 18 | OBJCPY=$(CROSS_COMPILE)objcopy 19 | 20 | ZIP = /usr/bin/zip 21 | RELEASE=`/bin/date +%Y%m%d`-rpi 22 | RELFILES=fs/ 23 | 24 | INC += -I. 25 | INC += -I$(TOP) 26 | INC += -I$(BUILD) 27 | 28 | # compiler settings 29 | CWARN = -Wall -Werror 30 | CWARN += -Wpointer-arith -Wuninitialized 31 | 32 | ifeq ($(BOARD),RPI1) 33 | CFLAGS_RPI = -marm -mcpu=arm1176jzf-s -mno-unaligned-access -DRPI1 34 | CFLAGS_FPU = -mfloat-abi=hard -mfpu=vfp 35 | ASFLAGS = --defsym RPI1=1 36 | else ifeq ($(BOARD),RPI2) 37 | CFLAGS_RPI = -marm -mcpu=cortex-a7 -mno-unaligned-access 38 | CFLAGS_FPU = -mfloat-abi=hard -mfpu=neon-vfpv4 39 | endif 40 | 41 | CFLAGS_RPI += $(CFLAGS_FPU) -fsingle-precision-constant -Wdouble-promotion 42 | CFLAGS = $(INC) $(CWARN) -std=c99 -nostdlib $(CFLAGS_RPI) $(CFLAGS_MOD) 43 | 44 | ASFLAGS += $(CFLAGS_FPU) 45 | 46 | #Debugging/Optimization 47 | ifeq ($(DEBUG), 1) 48 | CFLAGS += -O0 -gdwarf-2 49 | else 50 | CFLAGS += -Os -DNDEBUG 51 | endif 52 | 53 | CCVERSION:=$(shell $(CC) --version | sed 's/[ ]/\n/g' | grep "\." | xargs | awk '{ print $$1 }') 54 | ARMGCCLIBPATH=/usr/lib/gcc/arm-none-eabi/$(CCVERSION) 55 | 56 | LDFLAGS = -nostdlib -T kernel.ld -Map=$@.map --cref 57 | LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) 58 | 59 | SRC_LIB = $(addprefix lib/,\ 60 | libc/string0.c ) 61 | 62 | SRC_C = \ 63 | main.c \ 64 | uart.c \ 65 | rpi.c \ 66 | mphalport.c \ 67 | modmcu.c \ 68 | modutime.c \ 69 | modgpu.c \ 70 | modmachine.c \ 71 | bcm283x_gpio.c \ 72 | machine_pin.c \ 73 | arm_exceptions.c \ 74 | arm_ex_handler_weak.c \ 75 | machine_timer.c \ 76 | bcm283x_mailbox.c \ 77 | gpu.c \ 78 | gccollect.c \ 79 | mini-uart.c \ 80 | moduos.c \ 81 | fatfs_port.c \ 82 | sd.c \ 83 | machine_sdcard.c \ 84 | i2c.c \ 85 | machine_i2c.c \ 86 | spi.c \ 87 | machine_spi.c \ 88 | vc_property.c \ 89 | gpu_vc_property.c \ 90 | bcm283x_clockmgr.c \ 91 | pwm.c \ 92 | machine_pwm.c \ 93 | machine_clockmgr.c \ 94 | 95 | SRC_LIB = $(addprefix lib/,\ 96 | utils/stdout_helpers.c \ 97 | utils/sys_stdio_mphal.c \ 98 | utils/interrupt_char.c \ 99 | utils/pyexec.c \ 100 | libc/string0.c \ 101 | libm/math.c \ 102 | libm/fmodf.c \ 103 | libm/nearbyintf.c \ 104 | libm/ef_sqrt.c \ 105 | libm/log1pf.c \ 106 | libm/acoshf.c \ 107 | libm/asinhf.c \ 108 | libm/atanhf.c \ 109 | libm/kf_rem_pio2.c \ 110 | libm/kf_sin.c \ 111 | libm/kf_cos.c \ 112 | libm/kf_tan.c \ 113 | libm/ef_rem_pio2.c \ 114 | libm/erf_lgamma.c \ 115 | libm/sf_sin.c \ 116 | libm/sf_cos.c \ 117 | libm/sf_tan.c \ 118 | libm/sf_frexp.c \ 119 | libm/sf_modf.c \ 120 | libm/sf_ldexp.c \ 121 | libm/sf_erf.c \ 122 | libm/wf_lgamma.c \ 123 | libm/wf_tgamma.c \ 124 | libm/asinfacosf.c \ 125 | libm/atanf.c \ 126 | libm/atan2f.c \ 127 | mp-readline/readline.c \ 128 | timeutils/timeutils.c \ 129 | ) 130 | 131 | SRC_S = \ 132 | start.s \ 133 | gchelper.s \ 134 | 135 | # USB 136 | ifneq ($(MICROPY_HW_USBHOST),0) 137 | RELEASE :=$(RELEASE)-usb 138 | USBHOST_DIR=csud 139 | CSUDLIB=libcsud.a 140 | INC += -I$(USBHOST_DIR)/include 141 | CFLAGS += -DMICROPY_HW_USBHOST=$(MICROPY_HW_USBHOST) 142 | SRC_MOD += usbhost.c \ 143 | machine_usb_mode.c \ 144 | usbkbd.c \ 145 | 146 | LIB += -lcsud 147 | LDFLAGS += -no-wchar-size-warning 148 | USBLIB = $(BUILD)/$(CSUDLIB) 149 | 150 | $(USBLIB): 151 | $(ECHO) "MAKE $@" 152 | $(Q)$(MKDIR) -p $(BUILD)/$(USBHOST_DIR) 153 | $(Q)$(MAKE) -s -C $(USBHOST_DIR) driver CONFIG=FINAL TYPE=DRIVER TARGET=$(BOARD) GNU=$(CROSS_COMPILE) BUILD=../$(BUILD)/$(USBHOST_DIR)/ LIBNAME=../$(USBLIB) COPT="-Os $(CFLAGS_FPU)" 154 | 155 | endif 156 | 157 | # FatFS VFS support 158 | SRC_LIB += $(addprefix lib/,\ 159 | oofatfs/ff.c \ 160 | oofatfs/ffunicode.c \ 161 | ) 162 | CFLAGS += -DMICROPY_MOUNT_SD_CARD=$(MICROPY_MOUNT_SD_CARD) 163 | 164 | # List of sources for qstr extraction 165 | SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB) 166 | 167 | OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_MOD:.c=.o) $(SRC_S:.s=.o) $(SRC_LIB:.c=.o)) 168 | 169 | 170 | ifneq ($(FROZEN_DIR),) 171 | # To use frozen source modules, put your .py files in a subdirectory (eg scripts/) 172 | # and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). 173 | CFLAGS += -DMICROPY_MODULE_FROZEN_STR 174 | endif 175 | 176 | ifneq ($(FROZEN_MPY_DIR),) 177 | # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and 178 | # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). 179 | CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool 180 | CFLAGS += -DMICROPY_MODULE_FROZEN_MPY 181 | endif 182 | 183 | .PHONY: qemu 184 | 185 | 186 | all: $(BUILD)/firmware.img $(BUILD)/config.txt 187 | 188 | list: $(BUILD)/firmware.elf 189 | $(CROSS_COMPILE)objdump -d $(BUILD)/firmware.elf > $(BUILD)/firmware.list 190 | 191 | $(BUILD)/firmware.elf: $(OBJ) $(USBLIB) 192 | $(ECHO) "LINK $@" 193 | $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) 194 | $(Q)$(SIZE) $@ 195 | 196 | $(BUILD)/firmware.img: $(BUILD)/firmware.elf 197 | $(OBJCPY) $(BUILD)/firmware.elf -O binary $(BUILD)/firmware.img 198 | 199 | $(BUILD)/config.txt: config-template.txt 200 | $(ECHO) "GEN $@" 201 | $(Q)$(RM) -f $@ 202 | $(Q)$(CP) $< $@ 203 | $(Q)$(ECHO) "kernel=firmware.img" >> $@ 204 | 205 | release: $(BUILD)/firmware.img $(BUILD)/config.txt 206 | $(ECHO) "GEN $(BUILD)/$(RELEASE).zip" 207 | $(Q)$(ZIP) $(BUILD)/$(RELEASE) -jq $^ 208 | $(Q)cd $(RELFILES); $(ZIP) ../$(BUILD)/$(RELEASE) -rq . 209 | 210 | $(BUILD)/firmware-qemu.img: $(OBJ) $(USBLIB) 211 | $(ECHO) "LINK $@" 212 | $(Q)$(LD) --defsym=_load_addr=0x10000 $(LDFLAGS) -o $@.elf $^ $(LIBS) 213 | $(OBJCPY) $@.elf -O binary $@ 214 | 215 | ifeq ($(BOARD),RPI1) 216 | qemu: $(BUILD)/firmware-qemu.img 217 | @./qemu-system-arm \ 218 | -kernel $< \ 219 | -append "qemu" \ 220 | -cpu arm1176 \ 221 | -M versatilepb \ 222 | -m 512 \ 223 | -no-reboot \ 224 | -nographic \ 225 | -monitor null \ 226 | -serial stdio 227 | 228 | else ifeq ($(BOARD),RPI2) 229 | qemu: $(BUILD)/firmware-qemu.img 230 | @./qemu-system-arm \ 231 | -kernel $< \ 232 | -append "qemu" \ 233 | -M raspi2 \ 234 | -cpu arm1176 \ 235 | -m 1G \ 236 | -no-reboot \ 237 | -nographic \ 238 | -monitor null \ 239 | -smp 4 \ 240 | -serial stdio 241 | 242 | endif 243 | 244 | include $(TOP)/py/mkrules.mk 245 | 246 | $(BUILD)/%.o: %.s 247 | $(ECHO) "AS $<" 248 | $(Q)$(AS) $(ASFLAGS) -o $@ $< 249 | -------------------------------------------------------------------------------- /raspberrypi/arm_ex_handler_weak.c: -------------------------------------------------------------------------------- 1 | void __attribute__((weak, interrupt("UNDEF"))) undef_handler(void) { 2 | } 3 | 4 | void __attribute__((weak, interrupt("SWI"))) svc_handler(void) { 5 | } 6 | 7 | void __attribute__((weak, interrupt("ABORT"))) abort_handler(void) { 8 | } 9 | 10 | void __attribute__((weak, interrupt("IRQ"))) irq_handler(void) { 11 | } 12 | 13 | void __attribute__((weak, interrupt("IRQ"))) fiq_handler(void) { 14 | } 15 | 16 | -------------------------------------------------------------------------------- /raspberrypi/arm_exceptions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "arm_exceptions.h" 3 | 4 | // ldr pc, [pc, #24] 5 | #define JMP_PC_24 0xe59ff018 6 | 7 | 8 | extern void _start(void); // defined in start.s 9 | 10 | static void __attribute__((naked)) hangup(void) { 11 | while(1) { 12 | } 13 | } 14 | 15 | vector_table_t exception_vector = { \ 16 | .vector = { JMP_PC_24, JMP_PC_24, JMP_PC_24, JMP_PC_24, \ 17 | JMP_PC_24, JMP_PC_24, JMP_PC_24, JMP_PC_24 }, 18 | .reset = _start, 19 | .undef = undef_handler, 20 | .svc = svc_handler, 21 | .prefetch_abort = abort_handler, 22 | .data_abort = abort_handler, 23 | .hypervisor_trap = hangup, 24 | .irq = irq_handler, 25 | .fiq = fiq_handler 26 | }; 27 | 28 | static void set_vbar(vector_table_t *base) { 29 | __asm volatile ("mcr p15, 0, %[base], c12, c0, 0" 30 | :: [base] "r" (base)); 31 | } 32 | 33 | void arm_exceptions_init() { 34 | set_vbar(&exception_vector); 35 | } 36 | -------------------------------------------------------------------------------- /raspberrypi/arm_exceptions.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_EXCEPTIONS_H 2 | #define MICROPY_INCLUDED_RPI_EXCEPTIONS_H 3 | 4 | typedef void (*exception_hander_t)(void); 5 | 6 | typedef struct __attribute__((aligned(32))) _vector_table_t { 7 | const unsigned int vector[8]; // all elements shoud be JMP_PC_24 8 | exception_hander_t reset; 9 | exception_hander_t undef; 10 | exception_hander_t svc; 11 | exception_hander_t prefetch_abort; 12 | exception_hander_t data_abort; 13 | exception_hander_t hypervisor_trap; 14 | exception_hander_t irq; 15 | exception_hander_t fiq; 16 | } vector_table_t; 17 | 18 | extern vector_table_t exception_vector; 19 | 20 | void arm_exceptions_init(); 21 | 22 | __attribute__(( always_inline )) static inline void arm_irq_enable() { 23 | __asm volatile("mrs r0, cpsr \n" 24 | "bic r0, r0, #0x80 \n" 25 | "msr cpsr_c, r0 \n"); 26 | } 27 | 28 | __attribute__(( always_inline )) static inline void arm_irq_disable(){ 29 | __asm volatile("mrs r0, cpsr \n" 30 | "orr r0, r0, #0x80 \n" 31 | "msr cpsr_c, r0 \n"); 32 | } 33 | 34 | extern void __attribute__((interrupt("UNDEF"))) undef_handler(void); 35 | extern void __attribute__((interrupt("SWI"))) svc_handler(void); 36 | extern void __attribute__((interrupt("ABORT"))) abort_handler(void); 37 | extern void __attribute__((interrupt("IRQ"))) irq_handler(void); 38 | extern void __attribute__((interrupt("FIQ"))) fiq_handler(void); 39 | 40 | #endif // MICROPY_INCLUDED_RPI_EXCEPTIONS_H 41 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_H 3 | 4 | #include 5 | 6 | #ifdef RPI1 7 | #define IO_BASE 0x20000000U 8 | #else 9 | #define IO_BASE 0x3F000000U 10 | #endif 11 | 12 | #define IOREG(X) (*(volatile uint32_t *) (X)) 13 | 14 | #endif // MICROPY_INCLUDED_RPI_BCM283X_H 15 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_aux.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_AUX_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_AUX_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define AUX_BASE (0x215000 + IO_BASE) 7 | #define AUX(X) ((X) + AUX_BASE) 8 | 9 | #define AUX_IRQ IOREG(AUX(0x00)) 10 | #define AUX_ENABLES IOREG(AUX(0x04)) 11 | 12 | #define AUX_FLAG_MU (1) 13 | #define AUX_FLAG_SPI1 (1 << 1) 14 | #define AUX_FLAG_SPI2 (1 << 2) 15 | 16 | // top address of mini_uart_t 17 | #define AUX_MU AUX(0x40) 18 | 19 | typedef struct _mini_uart_t { 20 | uint32_t IO; 21 | uint32_t IER; 22 | uint32_t IIR; 23 | uint32_t LCR; 24 | uint32_t MCR; 25 | uint32_t LSR; 26 | uint32_t MSR; 27 | uint32_t SCRATCH; 28 | uint32_t CNTL; 29 | uint32_t STAT; 30 | uint32_t BAUD; 31 | } mini_uart_t; 32 | 33 | // The description of IER in the manual is incorrect. 34 | // Following definitions are from 16550's IER 35 | #define MU_IER_RX_AVAIL (1) 36 | #define MU_IER_TX_EMPTY (1 << 1) 37 | #define MU_IER_LSR_CHGD (1 << 2) 38 | 39 | #define MU_IIR_NOTHING (0) 40 | #define MU_IIR_TX_EMPTY (1 << 1) 41 | #define MU_IIR_RX_AVAIL (1 << 2) 42 | 43 | 44 | // aux spi not yet tested 45 | 46 | // top addresses of aux_spi_t 47 | #define AUX_SPI1 AUX(0x80) 48 | #define AUX_SPI2 AUX(0xC0) 49 | 50 | typedef struct _aux_spi_t { 51 | uint32_t CNTL0; 52 | uint32_t CNTL1; 53 | uint32_t STAT; 54 | uint32_t IO; 55 | uint32_t PEEK; 56 | } aux_spi_t; 57 | 58 | #endif // MICROPY_INCLUDED_RPI_BCM283X_AUX_H 59 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_clockmgr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bcm283x_clockmgr.h" 3 | 4 | void clockmgr_pause(clockmgr_t *clk) { 5 | if (clk->CTL & CM_CTL_ENAB) { 6 | clockmgr_set_ctl(clk, (clk->CTL & ~CM_CTL_ENAB)); 7 | while(clk->CTL & CM_CTL_BUSY) {}; 8 | } 9 | } 10 | 11 | void clockmgr_config_ctl(clockmgr_t *clk, int32_t flags) { 12 | clockmgr_pause(clk); 13 | clk->CTL = CM_PASSWORD | flags; 14 | } 15 | 16 | void clockmgr_config_div(clockmgr_t *clk, int32_t divi, int32_t divf) { 17 | uint32_t save = clk->CTL; 18 | clockmgr_pause(clk); 19 | clockmgr_set_div(clk, divi, divf); 20 | if (save & CM_CTL_ENAB) { 21 | clockmgr_set_ctl(clk, save); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_clockmgr.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_CLOCKMGR_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_CLOCKMGR_H 3 | 4 | #define CM_GP0 (IO_BASE + 0x101070) 5 | #define CM_GP1 (IO_BASE + 0x101078) 6 | #define CM_GP2 (IO_BASE + 0x101080) 7 | #define CM_PCM (IO_BASE + 0x101098) 8 | #define CM_PWM (IO_BASE + 0x1010a0) 9 | 10 | typedef volatile struct _clockmgr_t { 11 | uint32_t CTL; 12 | uint32_t DIV; 13 | } clockmgr_t; 14 | 15 | 16 | #define CM_PASSWORD (0x5a000000) 17 | 18 | #define CM_CTL_MASH_MASK (3U<<9) 19 | #define CM_CTL_MASH_IDIV (0U<<9) 20 | #define CM_CTL_MASH_1STG (1U<<9) 21 | #define CM_CTL_MASH_2STG (2U<<9) 22 | #define CM_CTL_MASH_3STG (3U<<9) 23 | 24 | #define CM_CTL_FLIP (1U<<8) 25 | #define CM_CTL_BUSY (1U<<7) 26 | #define CM_CTL_KILL (1U<<5) 27 | #define CM_CTL_ENAB (1U<<4) 28 | 29 | #define CM_CTL_SRC_MASK (0xfU) 30 | #define CM_CTL_SRC_GND (0U) 31 | #define CM_CTL_SRC_OSC (1U) 32 | #define CM_CTL_SRC_PLLA (4U) 33 | #define CM_CTL_SRC_PLLC (5U) 34 | #define CM_CTL_SRC_PLLD (6U) 35 | #define CM_CTL_SRC_HDMI (7U) 36 | 37 | #define CM_DIV_MASK (0x00ffffffU) 38 | 39 | __attribute__(( always_inline )) inline void clockmgr_set_ctl(clockmgr_t *clk, uint32_t ctl) { 40 | clk->CTL = CM_PASSWORD | (ctl & 0xffffff); 41 | } 42 | 43 | __attribute__(( always_inline )) inline void clockmgr_set_div(clockmgr_t *clk, uint32_t divi, uint32_t divf) { 44 | clk->DIV = CM_PASSWORD | (divi & 0xfff) << 12 | (divf & 0xfff); 45 | } 46 | 47 | void clockmgr_pause(clockmgr_t *clk); 48 | 49 | void clockmgr_config_ctl(clockmgr_t *clk, int32_t flags); 50 | 51 | void clockmgr_config_div(clockmgr_t *clk, int32_t divi, int32_t divf); 52 | 53 | #endif // MICROPY_INCLUDED_RPI_BCM283X_CLOCKMGR_H 54 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_gpio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bcm283x_gpio.h" 3 | 4 | void gpio_set_mode(uint32_t pin, uint32_t mode) { 5 | uint32_t reg; 6 | uint32_t pos; 7 | 8 | reg = GPFSEL0 + pin / 10 * 4; 9 | pos = (pin % 10) * 3; 10 | mode = mode & 7U; 11 | IOREG(reg) = (IOREG(reg) & ~(7 << pos)) | (mode << pos); 12 | } 13 | 14 | uint32_t gpio_get_mode(uint32_t pin) { 15 | uint32_t reg; 16 | uint32_t pos; 17 | 18 | reg = GPFSEL0 + pin / 10 * 4; 19 | pos = (pin % 10) * 3; 20 | return (IOREG(reg) >> pos) & 7U; 21 | } 22 | 23 | void gpio_set_level(uint32_t pin, uint32_t level) { 24 | uint32_t reg; 25 | 26 | reg = (pin > 31) ? 4 : 0; 27 | reg += (level == 0) ? GPCLR0 : GPSET0; 28 | IOREG(reg) = 1 << (pin & 0x1F); 29 | } 30 | 31 | uint32_t gpio_get_level(uint32_t pin) { 32 | uint32_t reg; 33 | 34 | reg = GPLEV0 + ((pin > 31) ? 4 : 0); 35 | if (IOREG(reg) & (1 << (pin & 0x1f))) { 36 | return 1; 37 | } else { 38 | return 0; 39 | } 40 | } 41 | 42 | static inline void delay_cycles(int32_t count) 43 | { 44 | __asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n" 45 | : "=r"(count): [count]"0"(count) : "cc"); 46 | } 47 | 48 | void gpio_set_pull_mode(uint32_t pin, uint32_t pud) { 49 | uint32_t reg; 50 | 51 | IOREG(GPPUD) = pud; 52 | delay_cycles(150); 53 | reg = GPPUDCLK0 + (pin >> 5) * 4; 54 | IOREG(reg) = 1 << (pin & 0x1f); 55 | delay_cycles(150); 56 | IOREG(GPPUD) = 0; 57 | IOREG(reg) = 0; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_GPIO_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_GPIO_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define GPIO_BASE (0x200000 + IO_BASE) 7 | #define GPIO(X) ((X) + GPIO_BASE) 8 | 9 | // GPIO registers 10 | 11 | #define GPFSEL0 GPIO(0x00) 12 | #define GPFSEL1 GPIO(0x04) 13 | #define GPFSEL2 GPIO(0x08) 14 | #define GPFSEL3 GPIO(0x0C) 15 | #define GPFSEL4 GPIO(0x10) 16 | #define GPFSEL5 GPIO(0x14) 17 | #define GPSET0 GPIO(0x1C) 18 | #define GPSET1 GPIO(0x20) 19 | #define GPCLR0 GPIO(0x28) 20 | #define GPCLR1 GPIO(0x2C) 21 | #define GPLEV0 GPIO(0x34) 22 | #define GPLEV1 GPIO(0x38) 23 | #define GPEDS0 GPIO(0x40) 24 | #define GPEDS1 GPIO(0x44) 25 | #define GPREN0 GPIO(0x4C) 26 | #define GPREN1 GPIO(0x50) 27 | #define GPFEN0 GPIO(0x58) 28 | #define GPFEN1 GPIO(0x5C) 29 | #define GPHEN0 GPIO(0x64) 30 | #define GPHEN1 GPIO(0x68) 31 | #define GPLEN0 GPIO(0x70) 32 | #define GPLEN1 GPIO(0x74) 33 | #define GPAREN0 GPIO(0x7C) 34 | #define GPAREN1 GPIO(0x80) 35 | #define GPAFEN0 GPIO(0x88) 36 | #define GPAFEN1 GPIO(0x8C) 37 | #define GPPUD GPIO(0x94) 38 | #define GPPUDCLK0 GPIO(0x98) 39 | #define GPPUDCLK1 GPIO(0x9C) 40 | 41 | // GPIO Alternate function selecter values 42 | #define GPF_INPUT 0U 43 | #define GPF_OUTPUT 1U 44 | #define GPF_ALT_0 4U 45 | #define GPF_ALT_1 5U 46 | #define GPF_ALT_2 6U 47 | #define GPF_ALT_3 7U 48 | #define GPF_ALT_4 3U 49 | #define GPF_ALT_5 2U 50 | 51 | // GPIO Pull-Up/Pull-Down (GPPUD) values 52 | #define GPPUD_NONE 0U 53 | #define GPPUD_EN_UP 1U 54 | #define GPPUD_EN_DOWN 2U 55 | 56 | // set / get GPIO Alternate function 57 | void gpio_set_mode(uint32_t pin, uint32_t mode); 58 | uint32_t gpio_get_mode(uint32_t pin); 59 | 60 | // set output mode GPIO pin to low or high 61 | void gpio_set_level(uint32_t pin, uint32_t level); 62 | 63 | // get input mode GPIO pin level (low or high) 64 | uint32_t gpio_get_level(uint32_t pin); 65 | 66 | // set input mode GPIO pin pull up mode (off or pull up or pull down) 67 | void gpio_set_pull_mode(uint32_t pin, uint32_t pud); 68 | 69 | #endif // MICROPY_INCLUDED_RPI_BCM283X_GPIO_H 70 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_I2C_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_I2C_H 3 | 4 | #define BSC0 (IO_BASE + 0x205000) 5 | #define BSC1 (IO_BASE + 0x804000) 6 | #define BSC2 (IO_BASE + 0x805000) 7 | 8 | typedef volatile struct _i2c_t { 9 | uint32_t C; 10 | uint32_t S; 11 | uint32_t DLEN; 12 | uint32_t A; 13 | uint32_t FIFO; 14 | uint32_t DIV; 15 | uint32_t DEL; 16 | uint32_t CLKT; 17 | } i2c_t; 18 | 19 | #define C_I2CEN (1<<15) 20 | #define C_INTR (1<<10) 21 | #define C_INTT (1<<9) 22 | #define C_INTD (1<<8) 23 | #define C_ST (1<<7) 24 | #define C_CLEAR (3<<4) 25 | #define C_READ (1) 26 | 27 | #define S_CLKT (1<<9) 28 | #define S_ERR (1<<8) 29 | #define S_RXF (1<<7) 30 | #define S_TXE (1<<6) 31 | #define S_RXD (1<<5) 32 | #define S_TXD (1<<4) 33 | #define S_RXR (1<<3) 34 | #define S_TXW (1<<2) 35 | #define S_DONE (1<<1) 36 | #define S_TA (1) 37 | 38 | #endif // MICROPY_INCLUDED_RPI_BCM283X_I2C_H 39 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_it.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_IT_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_IT_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define IRQ_PEND_BASIC IOREG(IO_BASE + 0xB200) 7 | #define IRQ_PEND1 IOREG(IO_BASE + 0xB204) 8 | #define IRQ_PEND2 IOREG(IO_BASE + 0xB208) 9 | #define IRQ_FIQ_CONTROL IOREG(IO_BASE + 0xB20C) 10 | #define IRQ_ENABLE1 IOREG(IO_BASE + 0xB210) 11 | #define IRQ_ENABLE2 IOREG(IO_BASE + 0xB214) 12 | #define IRQ_ENABLE_BASIC IOREG(IO_BASE + 0xB218) 13 | #define IRQ_DISABLE1 IOREG(IO_BASE + 0xB21C) 14 | #define IRQ_DISABLE2 IOREG(IO_BASE + 0xB220) 15 | #define IRQ_DISABLE_BASIC IOREG(IO_BASE + 0xB224) 16 | 17 | // IRQ_PEND_BASIC bits 18 | #define IRQ_ARM_TIMER (1) 19 | #define IRQ_MAILBOX (1 << 1) 20 | #define IRQ_DOORBELL0 (1 << 2) 21 | #define IRQ_DOORBELL1 (1 << 3) 22 | 23 | // IRQ_PEND1 bits 24 | #define IRQ_SYSTIMER(X) (1 << (X)) 25 | #define IRQ_AUX (1 << 29) 26 | 27 | // IRQ_PEND2 bits 28 | #define IRQ_GPIO(X) (1 << (17 + X)) 29 | #define IRQ_I2C (1 << 21) 30 | #define IRQ_SPI (1 << 22) 31 | #define IRQ_PCM (1 << 23) 32 | #define IRQ_UART (1 << 25) 33 | 34 | #endif // MICROPY_INCLUDED_RPI_BCM283X_IT_H 35 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_mailbox.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bcm283x_mailbox.h" 3 | 4 | void mailbox_write(uint8_t chan, uint32_t msg) { 5 | while ((MAILBOX1_STATUS & MAIL_FULL) != 0) { 6 | } 7 | MAILBOX1_FIFO = (msg << 4) | chan; 8 | } 9 | 10 | uint32_t mailbox_read(uint8_t chan) { 11 | uint32_t data; 12 | do { 13 | while (MAILBOX0_STATUS & MAIL_EMPTY) { 14 | } 15 | } while (((data = MAILBOX0_FIFO) & 0xfU) != chan); 16 | return data >> 4; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_mailbox.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_MAILBOX_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_MAILBOX_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define MAILBOX0_FIFO IOREG(IO_BASE + 0xB880) 7 | #define MAILBOX0_POLL IOREG(IO_BASE + 0xB890) 8 | #define MAILBOX0_SENDER IOREG(IO_BASE + 0xB894) 9 | #define MAILBOX0_STATUS IOREG(IO_BASE + 0xB898) 10 | #define MAILBOX0_CONFIG IOREG(IO_BASE + 0xB89C) 11 | #define MAILBOX1_FIFO IOREG(IO_BASE + 0xB8A0) 12 | #define MAILBOX1_POLL IOREG(IO_BASE + 0xB8B0) 13 | #define MAILBOX1_SENDER IOREG(IO_BASE + 0xB8B4) 14 | #define MAILBOX1_STATUS IOREG(IO_BASE + 0xB8B8) 15 | #define MAILBOX1_CONFIG IOREG(IO_BASE + 0xB8BC) 16 | 17 | #define MAIL_FULL 0x80000000U 18 | #define MAIL_EMPTY 0x40000000U 19 | 20 | #define MB_CH_POWER 0 21 | #define MB_CH_FRAMEBUF 1 22 | #define MB_CH_VUART 2 23 | #define MB_CH_VCHIQ 3 24 | #define MB_CH_LED 4 25 | #define MB_CH_BUTTON 5 26 | #define MB_CH_TOUCH 6 27 | #define MB_CH_RESERVED 7 28 | #define MB_CH_PROP_ARM 8 29 | #define MB_CH_PROP_VC 9 30 | 31 | #ifdef RPI1 32 | #define BUSADDR(a) (0x40000000 | (unsigned int) a) 33 | #else 34 | #define BUSADDR(a) (0xC0000000 | (unsigned int) a) 35 | #endif 36 | 37 | #define PHYSICALADDR(a) (0x3fffffff & (unsigned int) a) 38 | 39 | void mailbox_write(uint8_t chan, uint32_t msg); 40 | uint32_t mailbox_read(uint8_t chan); 41 | 42 | #endif // MICROPY_INCLUDED_RPI_BCM283X_MAILBOX_H 43 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_pwm.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_PWM_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_PWM_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define PWM (IO_BASE + 0x20C000) 7 | 8 | typedef volatile struct _pwm_t { 9 | uint32_t CTL; 10 | uint32_t STA; 11 | uint32_t DMAC; 12 | uint32_t undef1; 13 | uint32_t RNG1; 14 | uint32_t DAT1; 15 | uint32_t FIF1; 16 | uint32_t undef2; 17 | uint32_t RNG2; 18 | uint32_t DAT2; 19 | } pwm_t; 20 | 21 | #define CTL_MSEN2 (1<<15) 22 | #define CTL_USEF2 (1<<13) 23 | #define CTL_POLA2 (1<<12) 24 | #define CTL_SBIT2 (1<<11) 25 | #define CTL_RPTL2 (1<<10) 26 | #define CTL_MODE2 (1<<9) 27 | #define CTL_PWEN2 (1<<8) 28 | #define CTL_MSEN1 (1<<7) 29 | #define CTL_CLRF1 (1<<6) 30 | #define CTL_USEF1 (1<<5) 31 | #define CTL_POLA1 (1<<4) 32 | #define CTL_SBIT1 (1<<3) 33 | #define CTL_RPTL1 (1<<2) 34 | #define CTL_MODE1 (1<<1) 35 | #define CTL_PWEN1 (1) 36 | 37 | #define STA_STA4 (1<<12) 38 | #define STA_STA3 (1<<11) 39 | #define STA_STA2 (1<<10) 40 | #define STA_STA1 (1<<9) 41 | #define STA_BERR (1<<8) 42 | #define STA_GAPO4 (1<<7) 43 | #define STA_GAPO3 (1<<6) 44 | #define STA_GAPO2 (1<<5) 45 | #define STA_GAPO1 (1<<4) 46 | #define STA_RERR1 (1<<3) 47 | #define STA_WERR1 (1<<2) 48 | #define STA_EMPT1 (1<<1) 49 | #define STA_FULL1 (1) 50 | 51 | #define DMAC_ENAB (1<<31) 52 | #define DMAC_PANIC (255<<8) 53 | #define DMAC_DREQ (255) 54 | 55 | #endif // MICROPY_INCLUDED_RPI_BCM283X_PWM_H 56 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_spi.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_SPI_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_SPI_H 3 | 4 | #define SPI0 (IO_BASE + 0x204000) 5 | 6 | typedef volatile struct _spi_t { 7 | uint32_t CS; 8 | uint32_t FIFO; 9 | uint32_t CLK; 10 | uint32_t DLEN; 11 | uint32_t LTOH; 12 | uint32_t DC; 13 | } spi_t; 14 | 15 | #define CS_LEN_LONG (1<<25) 16 | #define CS_DMA_LEN (1<<24) 17 | #define CS_CSPOL2 (1<<23) 18 | #define CS_CSPOL1 (1<<22) 19 | #define CS_CSPOL0 (1<<21) 20 | #define CS_RXF (1<<20) 21 | #define CS_RXR (1<<19) 22 | #define CS_TXD (1<<18) 23 | #define CS_RXD (1<<17) 24 | #define CS_DONE (1<<16) 25 | #define CS_TE_EN (1<<15) 26 | #define CS_LMONO (1<<14) 27 | #define CS_LEN (1<<13) 28 | #define CS_REN (1<<12) 29 | #define CS_ADCS (1<<11) 30 | #define CS_INTR (1<<10) 31 | #define CS_INTD (1<<9) 32 | #define CS_DMAEN (1<<8) 33 | #define CS_TA (1<<7) 34 | #define CS_CSPOL (1<<6) 35 | #define CS_CLEAR (3<<4) 36 | #define CS_CPOL (1<<3) 37 | #define CS_CPHA (1<<2) 38 | #define CS_CS (3<<0) 39 | 40 | #define CLEAR_TX (1<<4) 41 | #define CLEAR_RX (2<<4) 42 | 43 | #endif // MICROPY_INCLUDED_RPI_BCM283X_SPI_H 44 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_systimer.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_SYSTIMER_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_SYSTIMER_H 3 | 4 | #define SYSTIMER (IO_BASE + 0x3000) 5 | 6 | typedef volatile struct systimer_t { 7 | uint32_t CS; 8 | uint32_t CLO; 9 | uint32_t CHI; 10 | uint32_t C[4]; 11 | } systimer_t; 12 | 13 | #endif // MICROPY_INCLUDED_RPI_BCM283X_SYSTIMER_H 14 | -------------------------------------------------------------------------------- /raspberrypi/bcm283x_uart.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_BCM283X_UART_H 2 | #define MICROPY_INCLUDED_RPI_BCM283X_UART_H 3 | 4 | #include "bcm283x.h" 5 | 6 | #define UART_BASE (0x201000 + IO_BASE) 7 | 8 | typedef struct _uart_t { 9 | uint32_t DR; 10 | uint32_t RSRECR; 11 | uint8_t reserved1[0x10]; 12 | const uint32_t FR; 13 | uint8_t reserved2[0x4]; 14 | uint32_t ILPR; 15 | uint32_t IBRD; 16 | uint32_t FBRD; 17 | uint32_t LCRH; 18 | uint32_t CR; 19 | uint32_t IFLS; 20 | uint32_t IMSC; 21 | const uint32_t RIS; 22 | const uint32_t MIS; 23 | uint32_t ICR; 24 | uint32_t DMACR; 25 | } uart_t; 26 | 27 | #endif // MICROPY_INCLUDED_RPI_BCM283X_UART_H 28 | -------------------------------------------------------------------------------- /raspberrypi/config-template.txt: -------------------------------------------------------------------------------- 1 | # Raspberry Pi boot configration 2 | # see https://www.raspberrypi.org/documentation/configuration/config-txt/ 3 | # for more details. 4 | 5 | # fake_vsync_isr=1 6 | # framebuffer_swap=0 7 | # gpu_mem=48 8 | # init_emmc_clock=100000000 9 | # arm_freq=1000 10 | # gpu_freq=300 11 | # core_freq=400 12 | # sdram_freq=450 13 | -------------------------------------------------------------------------------- /raspberrypi/fatfs_port.c: -------------------------------------------------------------------------------- 1 | #include "lib/oofatfs/ff.h" 2 | 3 | DWORD get_fattime(void) { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /raspberrypi/fs/README.txt: -------------------------------------------------------------------------------- 1 | copy these files to the root of your SD card. 2 | 3 | uncomment lines in main.py to use HDMI display as console screen. 4 | 5 | more info: https://github.com/boochow/micropython-raspberrypi 6 | -------------------------------------------------------------------------------- /raspberrypi/fs/boot.py: -------------------------------------------------------------------------------- 1 | # exec(open("./lib/ramdisk.py").read()) 2 | -------------------------------------------------------------------------------- /raspberrypi/fs/lib/fbconsole.py: -------------------------------------------------------------------------------- 1 | import framebuf 2 | import uio 3 | 4 | class FBConsole(uio.IOBase): 5 | def __init__(self, fb, bgcolor=0, fgcolor=-1, width=-1, height=-1, readobj=None): 6 | self.readobj = readobj 7 | self.fb = fb 8 | if width > 0: 9 | self.width=width 10 | else: 11 | try: 12 | self.width=fb.width 13 | except: 14 | raise ValueError 15 | if height > 0: 16 | self.height=height 17 | else: 18 | try: 19 | self.height=fb.height 20 | except: 21 | raise ValueError 22 | self.bgcolor = bgcolor 23 | self.fgcolor = fgcolor 24 | self.line_height(8) 25 | self.cls() 26 | 27 | def cls(self): 28 | self.x = 0 29 | self.y = 0 30 | self.y_end = 0 31 | self.fb.fill(self.bgcolor) 32 | try: 33 | self.fb.show() 34 | except: 35 | pass 36 | 37 | def line_height(self, px): 38 | self.lineheight = px 39 | self.w = self.width // px 40 | self.h = self.height // px 41 | 42 | def _putc(self, c): 43 | c = chr(c) 44 | if c == '\n': 45 | self._newline() 46 | elif c == '\x08': 47 | self._backspace() 48 | elif c >= ' ': 49 | self.fb.fill_rect(self.x * 8, self.y * self.lineheight, 8, self.lineheight, self.bgcolor) 50 | self.fb.text(c, self.x * 8, self.y * self.lineheight, self.fgcolor) 51 | self.x += 1 52 | if self.x >= self.w: 53 | self._newline() 54 | 55 | def _esq_read_num(self, buf, pos): 56 | digit = 1 57 | n = 0 58 | while buf[pos] != 0x5b: 59 | n += digit * (buf[pos] - 0x30) 60 | pos -= 1 61 | digit *= 10 62 | return n 63 | 64 | def write(self, buf): 65 | self._draw_cursor(self.bgcolor) 66 | i = 0 67 | while i < len(buf): 68 | c = buf[i] 69 | if c == 0x1b: 70 | i += 1 71 | esc = i 72 | while chr(buf[i]) in '[;0123456789': 73 | i += 1 74 | c = buf[i] 75 | if c == 0x4b and i == esc + 1: # ESC [ K 76 | self._clear_cursor_eol() 77 | elif c == 0x44: # ESC [ n D 78 | for _ in range(self._esq_read_num(buf, i - 1)): 79 | self._backspace() 80 | else: 81 | self._putc(c) 82 | i += 1 83 | self._draw_cursor(self.fgcolor) 84 | try: 85 | self.fb.show() 86 | except: 87 | pass 88 | return len(buf) 89 | 90 | def readinto(self, buf, nbytes=0): 91 | if self.readobj != None: 92 | return self.readobj.readinto(buf, nbytes) 93 | else: 94 | return None 95 | 96 | def _newline(self): 97 | self.x = 0 98 | self.y += 1 99 | if self.y >= self.h: 100 | self.fb.scroll(0, -8) 101 | self.fb.fill_rect(0, self.height - self.lineheight, self.width, self.lineheight, self.bgcolor) 102 | self.y = self.h - 1 103 | self.y_end = self.y 104 | 105 | def _backspace(self): 106 | if self.x == 0: 107 | if self.y > 0: 108 | self.y -= 1 109 | self.x = self.w - 1 110 | else: 111 | self.x -= 1 112 | 113 | def _clear_cursor_eol(self): 114 | self.fb.fill_rect(self.x * 8, self.y * self.lineheight, self.width, self.lineheight, self.bgcolor) 115 | for l in range(self.y + 1, self.y_end + 1): 116 | self.fb.fill_rect(0, l * self.lineheight, self.width, self.lineheight, self.bgcolor) 117 | self.y_end = self.y 118 | 119 | def _draw_cursor(self, color): 120 | self.fb.hline(self.x * 8, self.y * self.lineheight + 7, 8, color) 121 | -------------------------------------------------------------------------------- /raspberrypi/fs/lib/ramdisk.py: -------------------------------------------------------------------------------- 1 | class RAMBlockDev: 2 | def __init__(self, block_size, num_blocks): 3 | self.block_size = block_size 4 | self.data = bytearray(block_size * num_blocks) 5 | 6 | def readblocks(self, block_num, buf): 7 | for i in range(len(buf)): 8 | buf[i] = self.data[block_num * self.block_size + i] 9 | 10 | def writeblocks(self, block_num, buf): 11 | for i in range(len(buf)): 12 | self.data[block_num * self.block_size + i] = buf[i] 13 | 14 | def ioctl(self, op, arg): 15 | if op == 4: # get number of blocks 16 | return len(self.data) // self.block_size 17 | if op == 5: # get block size 18 | return self.block_size 19 | 20 | def mount_initrd(num_blocks, path): 21 | try: 22 | import uos 23 | bdev = RAMBlockDev(512, num_blocks) 24 | uos.VfsFat.mkfs(bdev) 25 | vfs = uos.VfsFat(bdev) 26 | uos.mount(vfs, path) 27 | except: 28 | print("error: mount_initrd") 29 | 30 | def create_ramdisk(): 31 | mount_initrd(2048, '/tmp') 32 | f=open('/tmp/RAM disk.txt', 'w') 33 | f.write(''' 34 | Size = 512 bytes * 2048 blocks 35 | Format = FAT16 36 | ''') 37 | f.close() 38 | 39 | if __name__ == '__main__': 40 | create_ramdisk() 41 | -------------------------------------------------------------------------------- /raspberrypi/fs/lib/rpi.py: -------------------------------------------------------------------------------- 1 | import gpu 2 | import framebuf 3 | 4 | class RPiScreen(framebuf.FrameBuffer): 5 | def __init__(self, width, height): 6 | self.width = width 7 | self.height = height 8 | gpu.fb_init(width,height,screen_w=1920,screen_h=1080) 9 | super().__init__(gpu.fb_data(),width,height,framebuf.RGB565) 10 | self 11 | 12 | def show(self): 13 | pass 14 | -------------------------------------------------------------------------------- /raspberrypi/fs/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | # from fbconsole import FBConsole 3 | # from rpi import RPiScreen 4 | 5 | # scr = FBConsole(RPiScreen(480,270)) 6 | # os.dupterm(scr) 7 | -------------------------------------------------------------------------------- /raspberrypi/gccollect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "py/obj.h" 31 | #include "py/gc.h" 32 | #include "py/mpthread.h" 33 | #include "gccollect.h" 34 | 35 | mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs); 36 | 37 | void gc_collect(void) { 38 | // get current time, in case we want to time the GC 39 | #if 0 40 | uint32_t start = mp_hal_ticks_us(); 41 | #endif 42 | 43 | // start the GC 44 | gc_collect_start(); 45 | 46 | // get the registers and the sp 47 | mp_uint_t regs[10]; 48 | mp_uint_t sp = gc_helper_get_regs_and_sp(regs); 49 | 50 | // trace the stack, including the registers (since they live on the stack in this function) 51 | #if MICROPY_PY_THREAD 52 | gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); 53 | #else 54 | gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t)); 55 | #endif 56 | 57 | // trace root pointers from any threads 58 | #if MICROPY_PY_THREAD 59 | mp_thread_gc_others(); 60 | #endif 61 | 62 | // end the GC 63 | gc_collect_end(); 64 | 65 | #if 0 66 | // print GC info 67 | uint32_t ticks = mp_hal_ticks_us() - start; 68 | gc_info_t info; 69 | gc_info(&info); 70 | printf("GC@%lu %lums\n", start, ticks); 71 | printf(" " UINT_FMT " total\n", info.total); 72 | printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); 73 | printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); 74 | #endif 75 | } 76 | -------------------------------------------------------------------------------- /raspberrypi/gccollect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | #ifndef MICROPY_INCLUDED_STM32_GCCOLLECT_H 27 | #define MICROPY_INCLUDED_STM32_GCCOLLECT_H 28 | 29 | // variables defining memory layout 30 | // (these probably belong somewhere else...) 31 | extern uint32_t _etext; 32 | extern uint32_t _sidata; 33 | extern uint32_t _ram_start; 34 | extern uint32_t _sdata; 35 | extern uint32_t _edata; 36 | extern uint32_t _sbss; 37 | extern uint32_t _ebss; 38 | extern uint32_t _heap_start; 39 | extern uint32_t _heap_end; 40 | extern uint32_t _estack; 41 | extern uint32_t _ram_end; 42 | 43 | #endif // MICROPY_INCLUDED_STM32_GCCOLLECT_H 44 | -------------------------------------------------------------------------------- /raspberrypi/gchelper.s: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | .text 3 | .code 32 4 | .align 4 5 | 6 | @ uint gc_helper_get_regs_and_sp(r0=uint regs[10]) 7 | .global gc_helper_get_regs_and_sp 8 | .type gc_helper_get_regs_and_sp, %function 9 | gc_helper_get_regs_and_sp: 10 | @ store registers into given array 11 | str r4, [r0], #4 12 | str r5, [r0], #4 13 | str r6, [r0], #4 14 | str r7, [r0], #4 15 | str r8, [r0], #4 16 | str r9, [r0], #4 17 | str r10, [r0], #4 18 | str r11, [r0], #4 19 | str r12, [r0], #4 20 | str r13, [r0], #4 21 | 22 | @ return the sp 23 | mov r0, sp 24 | bx lr 25 | 26 | -------------------------------------------------------------------------------- /raspberrypi/gpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gpu.h" 5 | 6 | void rpi_fb_init(fb_info_t *fb_info) { 7 | fb_info->buf_addr = 0; 8 | fb_info->buf_size = 0; 9 | fb_info->rowbytes = 0; 10 | while(fb_info->buf_addr == 0) { 11 | mailbox_write(MB_CH_FRAMEBUF, (uint32_t) BUSADDR(fb_info) >> 4); 12 | mailbox_read(MB_CH_FRAMEBUF); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /raspberrypi/gpu.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_GPU_H 2 | #define MICROPY_INCLUDED_RPI_GPU_H 3 | 4 | #include 5 | #include "bcm283x_mailbox.h" 6 | 7 | typedef volatile struct \ 8 | __attribute__((aligned(16))) _fb_info_t { 9 | uint32_t screen_w; //write display width 10 | uint32_t screen_h; //write display height 11 | uint32_t w; //write framebuffer width 12 | uint32_t h; //write framebuffer height 13 | uint32_t rowbytes; //write 0 to get value 14 | uint32_t bpp; //write bits per pixel 15 | uint32_t offset_x; //write x offset of framebuffer 16 | uint32_t offset_y; //write y offset of framebuffer 17 | uint32_t buf_addr; //write 0 to get value 18 | uint32_t buf_size; //write 0 to get value 19 | } fb_info_t; 20 | 21 | void rpi_fb_init(fb_info_t *fb_info); 22 | 23 | #endif // MICROPY_INCLUDED_RPI_GPU_H 24 | -------------------------------------------------------------------------------- /raspberrypi/gpu_vc_property.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/runtime.h" 5 | #include "py/obj.h" 6 | #include "py/mperrno.h" 7 | #include "bcm283x_mailbox.h" 8 | #include "vc_property.h" 9 | #include "gpu_vc_property.h" 10 | 11 | STATIC mp_obj_t gpu_vc_property(size_t n_args, const mp_obj_t *args) { 12 | mp_obj_t result = mp_const_none; 13 | 14 | if (n_args > 0) { 15 | unsigned int tag = mp_obj_get_int(args[0]); 16 | uint32_t *buf; 17 | uint32_t bufsize = vc_property_length(tag); 18 | 19 | if (bufsize == -2) { 20 | mp_raise_ValueError("unknown tag"); 21 | } else { 22 | if (bufsize == -1) { 23 | if ((tag == 0x0004400b) || (tag == 0x0004800b)) { 24 | // palette 25 | bufsize = 1032; 26 | } else { 27 | // all clocks or command line 28 | bufsize = 1024; 29 | } 30 | } 31 | 32 | // allocate buffer for mailbox 33 | // 24 bytes for buf[0..4] and end tag, + padding, 16 bytes aligned 34 | unsigned int msgsize = (bufsize + 24 + 15) & 0xfffffff0; 35 | // unsigned int msgsize = bufsize + 24; 36 | buf = (uint32_t *) m_new(uint8_t, msgsize); 37 | buf[0] = msgsize; 38 | buf[1] = MB_PROP_REQUEST; 39 | buf[2] = tag; 40 | buf[3] = bufsize; 41 | buf[4] = 0; 42 | 43 | // store args into mailbox 44 | int endtag = 5; // index to where endtag should be written 45 | int memsize = 0; // used for allocate memory tag (0x0003000c) 46 | mp_buffer_info_t bufinfo; // used when an argment is buffer type 47 | if ((n_args == 2) && (! mp_obj_is_integer(args[1]))) { 48 | // second arg may be buffer type or list or tuple 49 | if (mp_get_buffer(args[1], &bufinfo, MP_BUFFER_READ)) { 50 | if ((tag == 0x0003000d) || (tag == 0x0003000e) || \ 51 | (tag == 0x0003000f) || (tag == 0x00030014)) { 52 | // copy args[1] to buf as a handle 53 | buf[5] = (unsigned int) MP_OBJ_TO_PTR(args[1]); 54 | endtag += 1; 55 | } else { 56 | // copy data pointed from args[1] to buf 57 | if (bufinfo.len < buf[3]) { 58 | buf[3] = bufinfo.len; 59 | memcpy(&buf[5], bufinfo.buf, bufinfo.len); 60 | } else { 61 | memcpy(&buf[5], bufinfo.buf, buf[3]); 62 | } 63 | endtag += (buf[3] + 3) >> 2; // +3 for 4 bytes aligned 64 | } 65 | } else if (mp_obj_get_type(args[1]) == &mp_type_list) { 66 | // copy all integers in the list to buf 67 | mp_obj_list_t *o = (mp_obj_list_t *) args[1]; 68 | int maxargs = o->len; 69 | if (maxargs > buf[3] >> 2) { 70 | maxargs = buf[3] >> 2; 71 | } 72 | for (int i = 0; i < maxargs; i++) { 73 | buf[5 + i] = mp_obj_get_int(o->items[i]); 74 | } 75 | endtag += maxargs; 76 | } else if (mp_obj_get_type(args[1]) == &mp_type_tuple) { 77 | // copy all integers in the tuple to buf 78 | mp_obj_tuple_t *o = (mp_obj_tuple_t *) args[1]; 79 | int maxargs = o->len; 80 | if (maxargs > buf[3] >> 2) { 81 | maxargs = buf[3] >> 2; 82 | } 83 | for (int i = 0; i < maxargs; i++) { 84 | buf[5 + i] = mp_obj_get_int(o->items[i]); 85 | } 86 | endtag += maxargs; 87 | } else { 88 | mp_raise_ValueError("Invalid arguments"); 89 | } 90 | } else { 91 | // copy all arguments to buf as integer 92 | int maxargs = n_args - 1; 93 | if (maxargs > buf[3] >> 2) { 94 | maxargs = buf[3] >> 2; 95 | } 96 | for (int i = 1; i <= maxargs; i++) { 97 | if (mp_obj_is_integer(args[i])) { 98 | buf[4 + i] = mp_obj_get_int(args[i]); 99 | } else { 100 | mp_raise_ValueError("Invalid arguments"); 101 | } 102 | } 103 | endtag += buf[3] >> 2; 104 | } 105 | // end tag 106 | buf[endtag] = 0; 107 | 108 | // keep memsize for later use because buf[5] will be overwritten 109 | if (tag == 0x0003000c) { 110 | memsize = buf[5]; 111 | } 112 | /* 113 | for (int i = 0; i < buf[0] >> 2; i++) { 114 | printf("%08x ", (unsigned int) buf[i]); 115 | } 116 | printf("\n"); 117 | */ 118 | // request to get property through mailbox 119 | mailbox_write(MB_CH_PROP_ARM, (uint32_t) BUSADDR(buf) >> 4); 120 | mailbox_read(MB_CH_PROP_ARM); 121 | /* 122 | for (int i = 0; i < 5 + (((buf[4] + 3) & 0x7fffffff) >> 2); i++) { 123 | printf("%08x ", (unsigned int) buf[i]); 124 | } 125 | printf("\n"); 126 | */ 127 | if (buf[1] == MB_PROP_SUCCESS) { 128 | if (buf[4] & MB_PROP_SUCCESS) { 129 | uint32_t datalen = buf[4] & 0x7fffffff; 130 | if (datalen == 0) { 131 | // no data to return 132 | result = mp_const_none; 133 | } else if (datalen == 4) { 134 | if (tag == 0x0003000c) { // allocate mem 135 | result = mp_obj_new_bytearray_by_ref(memsize, (void *) buf[5]); 136 | } else if (tag == 0x00030014) { // get dispmanx handle 137 | if (buf[5] == 0) { 138 | result = mp_obj_new_bytearray_by_ref(bufinfo.len, (void *) buf[6]); 139 | } else { 140 | mp_raise_OSError(MP_EIO); 141 | } 142 | } else { 143 | // return an int32 value 144 | result = mp_obj_new_int(buf[5]); 145 | } 146 | } else if (tag == 0x00040001) { 147 | // return frame buffer or memory block as bytearray 148 | result = mp_obj_new_bytearray_by_ref(buf[6], (void *) buf[5]); 149 | } else if ((tag == 0x00010003) || (tag == 0x00030020)) { 150 | // return bytes (MAC address or EDID block) 151 | result = mp_obj_new_bytes((unsigned char *)&buf[5], datalen); 152 | } else if (tag == 0x00050001) { 153 | // return command line string 154 | vstr_t vstr; 155 | vstr_init_len(&vstr, datalen); 156 | if (vstr.len > 0) { 157 | memcpy(vstr.buf, &buf[5], vstr.len); 158 | result = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 159 | } else { 160 | mp_raise_OSError(MP_ENOMEM); 161 | } 162 | } else { 163 | // return a tuple of uint32_t 164 | result = mp_obj_new_tuple(datalen >> 2, NULL); 165 | mp_obj_tuple_t *o = (mp_obj_tuple_t *) result; 166 | for (size_t i = 0; i < o->len; i++) { 167 | o->items[i] = mp_obj_new_int(buf[5 + i]); 168 | } 169 | } 170 | } else { 171 | // failed getting this property value 172 | mp_raise_ValueError("Failed getting property value"); 173 | } 174 | } else { 175 | // failed getting property values 176 | mp_raise_ValueError("Mailbox returned 0x80000001"); 177 | } 178 | m_free(buf); 179 | } 180 | } 181 | return result; 182 | } 183 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gpu_vc_property_obj, 1, 8, gpu_vc_property); 184 | -------------------------------------------------------------------------------- /raspberrypi/gpu_vc_property.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_GPU_VC_PROP_H 2 | #define MICROPY_INCLUDED_RPI_GPU_VC_PROP_H 3 | 4 | MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(gpu_vc_property_obj); 5 | 6 | #endif // MICROPY_INCLUDED_RPI_GPU_VC_PROP_H 7 | -------------------------------------------------------------------------------- /raspberrypi/i2c.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "py/mpconfig.h" 4 | #include "py/mperrno.h" 5 | #include "bcm283x_i2c.h" 6 | #include "rpi.h" 7 | #include "i2c.h" 8 | 9 | void i2c_init(i2c_t *i2c) { 10 | i2c->S |= S_CLKT | S_ERR | S_DONE; 11 | i2c->C |= C_I2CEN | C_CLEAR; 12 | } 13 | 14 | void i2c_deinit(i2c_t *i2c) { 15 | i2c->S |= S_CLKT | S_ERR | S_DONE; 16 | i2c->C |= C_CLEAR; 17 | i2c->C = i2c->C & ~C_I2CEN; 18 | } 19 | 20 | void i2c_start(i2c_t *i2c) { 21 | i2c->C |= C_ST; 22 | } 23 | 24 | /* 25 | i2c_abort_write(i2c) is used for generating pseudo stop condition. 26 | Since bcm2835 I2C controller automatically generates stop condition 27 | when the amount of transfer reaches to DLEN, it is impossible to 28 | determine the timing of generating stop condition AFTER a transfer 29 | started. So I made this function to "break" on-going transfer and 30 | generate stop condition whenever it is necessary. The transfer used 31 | with this function should set DLEN large enough to avoid automatic 32 | stop condition generation. 33 | */ 34 | void i2c_abort_write(i2c_t *i2c) { 35 | while (!(i2c->S & S_TXE)); 36 | i2c_clear_fifo(i2c); 37 | } 38 | 39 | int i2c_busy(i2c_t *i2c) { 40 | return (i2c->S & S_TA) && ((i2c->S & S_DONE) == 0); 41 | } 42 | 43 | void i2c_clear_fifo(i2c_t *i2c) { 44 | i2c->C |= C_CLEAR; 45 | } 46 | 47 | int i2c_result(i2c_t *i2c) { 48 | if (i2c->S & S_ERR) { 49 | // No Ack Error 50 | i2c->S |= S_ERR; 51 | return -MP_EIO; 52 | } else if (i2c->S & S_CLKT) { 53 | // Timeout Error 54 | i2c->S |= S_CLKT; 55 | return -MP_ETIMEDOUT; 56 | } else if (i2c->S & S_DONE) { 57 | // Transfer Done 58 | i2c->S |= S_DONE; 59 | } 60 | return 0; 61 | } 62 | 63 | void i2c_write_start(i2c_t *i2c, bool stop) { 64 | // Note: you can't send a start bit without determining the 65 | // next operation will be reading or writing. 66 | // This function assumes the operation is "wriiting". 67 | if ((i2c->S & S_TA) && ((i2c->C & C_READ) == 0)){ 68 | // previous write transfer is still active 69 | i2c_abort_write(i2c); 70 | } 71 | i2c->S |= S_DONE | S_ERR | S_CLKT; 72 | i2c->C = i2c->C & ~C_READ; 73 | i2c->DLEN = 0xffff; 74 | i2c_start(i2c); 75 | } 76 | 77 | int i2c_write(i2c_t *i2c, const uint8_t *buf, const uint32_t buflen, bool stop) { 78 | int len = buflen; 79 | bool continued = false; 80 | 81 | if ((i2c->S & S_TA) && ((i2c->C & C_READ) == 0)){ 82 | // previous write transfer is still active (maybe stop=False) 83 | continued = true; 84 | } else { 85 | // start new transfer 86 | i2c->S |= S_DONE | S_ERR | S_CLKT; 87 | i2c->C = i2c->C & ~C_READ; 88 | while ((i2c->S & S_TXD) && (len != 0)){ 89 | i2c->FIFO = *buf++; 90 | --len; 91 | } 92 | if (stop) { 93 | i2c->DLEN = buflen; 94 | } else { 95 | // do not STOP after sending all data in buf; see i2c_abort_write() 96 | i2c->DLEN = 0xffff; 97 | } 98 | i2c_start(i2c); 99 | do { } while (!(i2c->S & S_TA)); 100 | } 101 | for(;;) { 102 | if (i2c->S & (S_ERR | S_CLKT)) { 103 | // error occured 104 | return i2c_result(i2c); 105 | } else if (stop && (i2c->S & S_DONE)) { 106 | // transfer success 107 | return buflen - len; 108 | } else if (!stop && (len == 0)) { 109 | // maybe transfer success 110 | return buflen - len; 111 | } 112 | 113 | if (continued && (len == 0)) { 114 | if (stop) { 115 | i2c_abort_write(i2c); 116 | while (!(i2c->S & S_DONE)); 117 | } 118 | return buflen; 119 | } 120 | 121 | while ((i2c->S & S_TXD) && (len != 0)) { 122 | i2c->FIFO = *buf++; 123 | --len; 124 | } 125 | } 126 | } 127 | 128 | int i2c_read(i2c_t *i2c, uint8_t *buf, const uint32_t readlen) { 129 | if ((i2c->S & S_TA) && ((i2c->C & C_READ) == 0)){ 130 | // previous write transfer is still active 131 | i2c_abort_write(i2c); 132 | } else { 133 | i2c->S |= S_DONE | S_ERR | S_CLKT; 134 | } 135 | i2c->DLEN = readlen; 136 | i2c->C |= C_READ; 137 | i2c_start(i2c); 138 | int len = readlen; 139 | for(;;) { 140 | if (i2c->S & (S_ERR | S_CLKT)) { 141 | // error occured 142 | return i2c_result(i2c); 143 | } else if (i2c->S & S_DONE) { 144 | // transfer success 145 | return readlen - len; 146 | } 147 | 148 | if (i2c->S & S_RXD) { 149 | uint8_t data = i2c->FIFO & 0xffU; 150 | if (len != 0) { 151 | *buf++ = data; 152 | len--; 153 | } 154 | } 155 | } 156 | } 157 | 158 | void i2c_set_clock_speed(i2c_t *i2c, uint32_t speed) { 159 | uint32_t cdiv = rpi_freq_core() / speed; 160 | cdiv = (cdiv < 2) ? 2 : cdiv; 161 | cdiv = (cdiv > 0xfffe) ? 0xfffe : cdiv; 162 | uint32_t fedl = (cdiv > 15) ? (cdiv / 16) : 1; 163 | uint32_t redl = (cdiv > 3) ? (cdiv / 4) : 1; 164 | i2c->DIV = cdiv; 165 | i2c->DEL = (fedl << 16) | redl; 166 | } 167 | 168 | uint32_t i2c_get_clock_speed(i2c_t *i2c) { 169 | uint32_t val = i2c->DIV & 0x7fff; 170 | if (val == 0) { 171 | val = 32768; 172 | } 173 | return rpi_freq_core() / val; 174 | } 175 | -------------------------------------------------------------------------------- /raspberrypi/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_I2C_H 2 | #define MICROPY_INCLUDED_RPI_I2C_H 3 | 4 | #include 5 | #include "bcm283x_i2c.h" 6 | 7 | void i2c_init(i2c_t *i2c); 8 | void i2c_deinit(i2c_t *i2c); 9 | void i2c_write_start(i2c_t *i2c, bool stop); 10 | int i2c_write(i2c_t *i2c, const uint8_t *buf, const uint32_t buflen, bool stop); 11 | int i2c_read(i2c_t *i2c, uint8_t *buf, const uint32_t readlen); 12 | 13 | void i2c_clear_fifo(i2c_t *i2c); 14 | #define i2c_set_slave(i2c, addr) ((i2c)->A = (addr) & 0x7FU) 15 | #define i2c_get_slave(i2c) ((i2c)->A & 0x7FU) 16 | void i2c_set_clock_speed(i2c_t *i2c, uint32_t speed); 17 | uint32_t i2c_get_clock_speed(i2c_t *i2c); 18 | int i2c_busy(i2c_t *i2c); 19 | 20 | #endif // MICROPY_INCLUDED_RPI_I2C_H 21 | -------------------------------------------------------------------------------- /raspberrypi/kernel.ld: -------------------------------------------------------------------------------- 1 | SECTIONS { 2 | . = DEFINED(_load_addr) ? _load_addr : 0x8000; 3 | .init . : { *(.init) } 4 | . = ALIGN(4); 5 | 6 | .text : { *(.text) } 7 | . = ALIGN(4); 8 | 9 | .data : { *(.data) } 10 | . = ALIGN(4); 11 | 12 | _bss_start = .; 13 | .bss : { *(.bss COMMON) } 14 | . = ALIGN(4); 15 | _bss_end = .; 16 | 17 | . = . + 0x1000; 18 | _heap_start = .; 19 | _ram_start = .; 20 | . = . + 0x4000000; 21 | _heap_end = .; 22 | 23 | . = 0x8000000; 24 | _estack = .; 25 | _ram_end = .; 26 | } 27 | -------------------------------------------------------------------------------- /raspberrypi/machine_clockmgr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/runtime.h" 5 | #include "modmachine.h" 6 | #include "bcm283x_gpio.h" 7 | #include "bcm283x_clockmgr.h" 8 | 9 | typedef struct _machine_clock_obj_t { 10 | mp_obj_base_t base; 11 | clockmgr_t *clock_reg; 12 | } machine_clock_obj_t; 13 | 14 | enum { ARG_enable, ARG_source, ARG_mash, ARG_divi, ARG_divf }; 15 | static const mp_arg_t allowed_args[] = { 16 | { MP_QSTR_enable, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 17 | { MP_QSTR_source, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 18 | { MP_QSTR_mash, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 19 | { MP_QSTR_divi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 20 | { MP_QSTR_divf, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 21 | }; 22 | 23 | STATIC mp_obj_t machine_clock_init_helper(machine_clock_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 24 | // parse args 25 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 26 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 27 | 28 | // initialize clock manager 29 | uint32_t ctl_save = self->clock_reg->CTL; 30 | uint32_t reg = 0; 31 | if (mp_obj_is_integer(args[ARG_enable].u_obj)) { 32 | if (mp_obj_get_int(args[ARG_enable].u_obj) != 0) { 33 | reg |= CM_CTL_ENAB; 34 | } 35 | } else { 36 | reg |= (ctl_save & CM_CTL_ENAB); 37 | } 38 | 39 | if (MP_OBJ_IS_INT(args[ARG_source].u_obj)) { 40 | reg |= mp_obj_get_int(args[ARG_source].u_obj) & CM_CTL_SRC_MASK; 41 | } else { 42 | reg |= (ctl_save & CM_CTL_SRC_MASK); 43 | } 44 | 45 | if (MP_OBJ_IS_INT(args[ARG_mash].u_obj)) { 46 | reg |= (mp_obj_get_int(args[ARG_mash].u_obj) << 9) & CM_CTL_MASH_MASK; 47 | } else { 48 | reg |= (ctl_save & CM_CTL_MASH_MASK); 49 | } 50 | 51 | if (reg != (ctl_save & (CM_CTL_MASH_MASK | CM_CTL_SRC_MASK))) { 52 | clockmgr_config_ctl(self->clock_reg, reg); 53 | } 54 | // configure clock divisor 55 | uint32_t divi = 0; 56 | uint32_t divf = 0; 57 | if (mp_obj_is_integer(args[ARG_divi].u_obj)) { 58 | divi = mp_obj_get_int(args[ARG_divi].u_obj); 59 | } 60 | 61 | if (mp_obj_is_integer(args[ARG_divf].u_obj)) { 62 | divf = mp_obj_get_int(args[ARG_divi].u_obj); 63 | } 64 | 65 | if ((divi != 0) || (divf != 0)){ 66 | clockmgr_set_div(self->clock_reg, divi, divf); 67 | } 68 | 69 | return (mp_obj_t *) self; 70 | } 71 | 72 | STATIC mp_obj_t machine_clock_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { 73 | return machine_clock_init_helper(args[0], n_args - 1, args + 1, kw_args); 74 | } 75 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_clock_init_obj, 1, machine_clock_init); 76 | 77 | STATIC mp_obj_t machine_clock_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { 78 | // make new clock object 79 | uint32_t reg = mp_obj_get_int(all_args[0]); 80 | if ((reg != CM_GP0) && (reg != CM_GP1) && (reg != CM_GP2) && (reg != CM_PCM) && (reg != CM_PWM)){ 81 | mp_raise_ValueError("invalid register address"); 82 | } 83 | machine_clock_obj_t *self = m_new_obj(machine_clock_obj_t); 84 | self->base.type = &machine_clock_type; 85 | self->clock_reg = (clockmgr_t *) reg; 86 | // initialize clock manager 87 | if (n_args > 1 || n_kw > 0) { 88 | mp_map_t kw_args; 89 | mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); 90 | machine_clock_init_helper(self, n_args - 1, all_args + 1, &kw_args); 91 | } 92 | 93 | return (mp_obj_t *) self; 94 | } 95 | 96 | STATIC mp_obj_t machine_clock_divisor(size_t n_args, const mp_obj_t *args) { 97 | machine_clock_obj_t *self = (machine_clock_obj_t*) MP_OBJ_TO_PTR(args[0]); 98 | uint32_t divi = 0; 99 | uint32_t divf = 0; 100 | 101 | if (n_args == 1) { 102 | // return a tuple of (divi, divf) 103 | divi = (self->clock_reg->DIV >> 12) & 0xfffU; 104 | divf = self->clock_reg->DIV & 0xfffU; 105 | mp_obj_tuple_t *result = mp_obj_new_tuple(2, NULL); 106 | result->items[0] = mp_obj_new_int(divi); 107 | result->items[1] = mp_obj_new_int(divf); 108 | return (mp_obj_t *) result; 109 | } else { 110 | if (mp_obj_is_integer(args[1])) { 111 | divi = mp_obj_get_int(args[1]); 112 | } 113 | if ((n_args == 3) && (mp_obj_is_integer(args[2]))) { 114 | divf = mp_obj_get_int(args[2]); 115 | } 116 | clockmgr_set_div(self->clock_reg, divi, divf); 117 | } 118 | return mp_const_none; 119 | } 120 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_clock_divisor_obj, 1, 3, machine_clock_divisor); 121 | 122 | STATIC const mp_rom_map_elem_t machine_clock_locals_dict_table[] = { 123 | // instance methods 124 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_clock_init_obj) }, 125 | { MP_ROM_QSTR(MP_QSTR_divisor), MP_ROM_PTR(&machine_clock_divisor_obj) }, 126 | // class constants 127 | { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_INT(CM_GP0) }, 128 | { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_INT(CM_GP1) }, 129 | { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_INT(CM_GP2) }, 130 | { MP_ROM_QSTR(MP_QSTR_PCM), MP_ROM_INT(CM_PCM) }, 131 | { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(CM_PWM) }, 132 | { MP_ROM_QSTR(MP_QSTR_OSC), MP_ROM_INT(CM_CTL_SRC_OSC) }, 133 | { MP_ROM_QSTR(MP_QSTR_PLLC), MP_ROM_INT(CM_CTL_SRC_PLLC) }, 134 | { MP_ROM_QSTR(MP_QSTR_PLLD), MP_ROM_INT(CM_CTL_SRC_PLLD) }, 135 | { MP_ROM_QSTR(MP_QSTR_HDMI), MP_ROM_INT(CM_CTL_SRC_HDMI) }, 136 | }; 137 | 138 | STATIC MP_DEFINE_CONST_DICT(machine_clock_locals_dict, machine_clock_locals_dict_table); 139 | 140 | const mp_obj_type_t machine_clock_type = { 141 | { &mp_type_type }, 142 | .name = MP_QSTR_Clock, 143 | .make_new = machine_clock_make_new, 144 | .locals_dict = (mp_obj_dict_t*) &machine_clock_locals_dict, 145 | }; 146 | 147 | -------------------------------------------------------------------------------- /raspberrypi/machine_i2c.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "py/mperrno.h" 6 | #include "py/runtime.h" 7 | #include "py/mphal.h" 8 | #include "py/mperrno.h" 9 | #include "bcm283x_gpio.h" 10 | #include "bcm283x_i2c.h" 11 | #include "rpi.h" 12 | #include "i2c.h" 13 | #include "modmachine.h" 14 | 15 | #define I2C_DEFAULT_FREQ (100000) 16 | 17 | typedef struct _machine_i2c_obj_t { 18 | mp_obj_base_t base; 19 | uint32_t id; 20 | i2c_t *i2c; 21 | } machine_i2c_obj_t; 22 | 23 | const machine_i2c_obj_t machine_i2c_obj[] = { 24 | {{&machine_i2c_type}, 0, (i2c_t *) BSC0}, 25 | {{&machine_i2c_type}, 1, (i2c_t *) BSC1}, 26 | {{&machine_i2c_type}, 2, (i2c_t *) BSC2}, 27 | }; 28 | 29 | static void i2c_gpio_setup(uint32_t id, bool on) { 30 | if (on) { 31 | switch(id) { 32 | case 0: 33 | gpio_set_mode(0, GPF_ALT_0); 34 | gpio_set_mode(1, GPF_ALT_0); 35 | break; 36 | case 1: 37 | gpio_set_mode(2, GPF_ALT_0); 38 | gpio_set_mode(3, GPF_ALT_0); 39 | break; 40 | case 2: 41 | break; 42 | default: 43 | ; 44 | } 45 | } else { 46 | switch(id) { 47 | case 0: 48 | gpio_set_mode(0, GPF_INPUT); 49 | gpio_set_mode(1, GPF_INPUT); 50 | break; 51 | case 1: 52 | gpio_set_mode(2, GPF_INPUT); 53 | gpio_set_mode(3, GPF_INPUT); 54 | break; 55 | case 2: 56 | break; 57 | default: 58 | ; 59 | } 60 | } 61 | } 62 | 63 | 64 | enum { ARG_freq }; 65 | static const mp_arg_t allowed_args[] = { 66 | { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_DEFAULT_FREQ} }, 67 | }; 68 | 69 | STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { 70 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 71 | // parse args 72 | int id = mp_obj_get_int(all_args[0]); 73 | if (id > 2) { 74 | mp_raise_ValueError("invalid bus number"); 75 | } 76 | machine_i2c_obj_t *i2c = (machine_i2c_obj_t*) &machine_i2c_obj[id]; 77 | mp_arg_parse_all_kw_array(--n_args, n_kw, ++all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 78 | 79 | // set up GPIO alternate function 80 | i2c_gpio_setup(id, true); 81 | 82 | // initialize I2C controller 83 | i2c_init(i2c->i2c); 84 | i2c_set_clock_speed(i2c->i2c, args[0].u_int); 85 | 86 | return i2c; 87 | } 88 | 89 | STATIC mp_obj_t machine_i2c_init_helper(machine_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 90 | // parse args 91 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 92 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 93 | 94 | // set up GPIO alternate function 95 | i2c_gpio_setup(self->id, true); 96 | 97 | // initialize I2C controller 98 | i2c_init(self->i2c); 99 | i2c_set_clock_speed(self->i2c, args[0].u_int); 100 | 101 | return mp_const_none; 102 | } 103 | 104 | STATIC mp_obj_t machine_i2c_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { 105 | return machine_i2c_init_helper(args[0], n_args - 1, args + 1, kw_args); 106 | } 107 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 0, machine_i2c_init); 108 | 109 | STATIC mp_obj_t machine_i2c_deinit(mp_obj_t self_in) { 110 | machine_i2c_obj_t *self = self_in; 111 | 112 | // de-initialize I2C controller 113 | i2c_deinit(self->i2c); 114 | 115 | // set GPIO to input mode 116 | i2c_gpio_setup(self->id, false); 117 | 118 | return mp_const_none; 119 | } 120 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_deinit_obj, machine_i2c_deinit); 121 | 122 | STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { 123 | machine_i2c_obj_t *self = self_in; 124 | uint32_t freq = i2c_get_clock_speed(self->i2c); 125 | mp_printf(print, "I2C(%u", self->id); 126 | if (freq != I2C_DEFAULT_FREQ) { 127 | mp_printf(print, ", freq=%u", freq); 128 | } 129 | mp_printf(print, ")"); 130 | } 131 | 132 | /// \method writeto(addr, buf) 133 | /// \method readfrom(addr, num) 134 | 135 | STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { 136 | machine_i2c_obj_t *self = (machine_i2c_obj_t*)MP_OBJ_TO_PTR(args[0]); 137 | mp_int_t addr = mp_obj_get_int(args[1]); 138 | mp_buffer_info_t bufinfo; 139 | mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); 140 | bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); 141 | 142 | i2c_set_slave(self->i2c, addr); 143 | i2c_write_start(self->i2c, stop); 144 | int ret = i2c_write(self->i2c, bufinfo.buf, bufinfo.len, stop); 145 | if (ret < 0) { 146 | i2c_clear_fifo(self->i2c); 147 | mp_raise_OSError(-ret); 148 | } 149 | 150 | return MP_OBJ_NEW_SMALL_INT(ret); 151 | } 152 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto); 153 | 154 | STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t slave, mp_obj_t buf) { 155 | machine_i2c_obj_t *self = (machine_i2c_obj_t*) MP_OBJ_TO_PTR(self_in); 156 | mp_int_t addr = mp_obj_get_int(slave); 157 | mp_buffer_info_t bufinfo; 158 | mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); 159 | i2c_set_slave(self->i2c, addr); 160 | int ret = i2c_read(self->i2c, (uint8_t*)bufinfo.buf, bufinfo.len); 161 | if (ret < 0) { 162 | i2c_clear_fifo(self->i2c); 163 | mp_raise_OSError(-ret); 164 | } 165 | return mp_const_none; 166 | } 167 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into); 168 | 169 | STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t slave, mp_obj_t len) { 170 | machine_i2c_obj_t *self = (machine_i2c_obj_t*) MP_OBJ_TO_PTR(self_in); 171 | mp_int_t addr = mp_obj_get_int(slave); 172 | vstr_t vstr; 173 | vstr_init_len(&vstr, mp_obj_get_int(len)); 174 | i2c_set_slave(self->i2c, addr); 175 | int ret = i2c_read(self->i2c, (uint8_t*)vstr.buf, vstr.len); 176 | if (ret < 0) { 177 | i2c_clear_fifo(self->i2c); 178 | mp_raise_OSError(-ret); 179 | } 180 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 181 | } 182 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom); 183 | 184 | STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { 185 | machine_i2c_obj_t *self = (machine_i2c_obj_t*) MP_OBJ_TO_PTR(self_in); 186 | mp_obj_t list = mp_obj_new_list(0, NULL); 187 | // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved 188 | for (int addr = 0x08; addr < 0x78; ++addr) { 189 | while(i2c_busy(self->i2c)); 190 | mp_hal_delay_ms(1); 191 | i2c_set_slave(self->i2c, addr); 192 | uint8_t buf = 0; 193 | int ret; 194 | if (((0x30 <= addr) && (addr <= 0x37)) 195 | || ((0x50 <= addr) && (addr <= 0x5f))) { 196 | ret = i2c_read(self->i2c, &buf, 1); 197 | } else { 198 | ret = i2c_write(self->i2c, &buf, 0, true); 199 | } 200 | if (ret >= 0) { 201 | mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); 202 | } 203 | } 204 | return list; 205 | } 206 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); 207 | 208 | STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { 209 | machine_i2c_obj_t *self = (machine_i2c_obj_t*) MP_OBJ_TO_PTR(self_in); 210 | 211 | // write memory address 212 | i2c_set_slave(self->i2c, addr); 213 | 214 | uint8_t memaddr_buf[4]; 215 | size_t memaddr_len = 0; 216 | for (int16_t i = addrsize - 8; i >= 0; i -= 8) { 217 | memaddr_buf[memaddr_len++] = memaddr >> i; 218 | } 219 | int ret = i2c_write(self->i2c, memaddr_buf, memaddr_len, false); 220 | if (ret < 0) { 221 | i2c_clear_fifo(self->i2c); 222 | } else { 223 | // read from the slave 224 | ret = i2c_read(self->i2c, buf, len); 225 | if (ret < 0) { 226 | i2c_clear_fifo(self->i2c); 227 | } 228 | } 229 | return ret; 230 | } 231 | 232 | STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = { 233 | { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, 234 | { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, 235 | { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, 236 | { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, 237 | }; 238 | 239 | STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 240 | enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; 241 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; 242 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, 243 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); 244 | 245 | // create the buffer to store data into 246 | vstr_t vstr; 247 | vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj)); 248 | 249 | // do the transfer 250 | int ret = read_mem(pos_args[0], \ 251 | args[ARG_addr].u_int, \ 252 | args[ARG_memaddr].u_int, \ 253 | args[ARG_addrsize].u_int, \ 254 | (uint8_t*)vstr.buf, vstr.len); 255 | if (ret < 0) { 256 | mp_raise_OSError(-ret); 257 | } 258 | 259 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 260 | } 261 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); 262 | 263 | STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 264 | enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; 265 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; 266 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, 267 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); 268 | 269 | // get the buffer to store data into 270 | mp_buffer_info_t bufinfo; 271 | mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); 272 | 273 | // do the transfer 274 | int ret = read_mem(pos_args[0], \ 275 | args[ARG_addr].u_int, \ 276 | args[ARG_memaddr].u_int, \ 277 | args[ARG_addrsize].u_int, \ 278 | bufinfo.buf, bufinfo.len); 279 | if (ret < 0) { 280 | mp_raise_OSError(-ret); 281 | } 282 | 283 | return mp_const_none; 284 | } 285 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); 286 | 287 | #define MAX_MEMADDR_SIZE (4) 288 | 289 | STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 290 | enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; 291 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; 292 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, 293 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); 294 | machine_i2c_obj_t *self = (machine_i2c_obj_t*) MP_OBJ_TO_PTR(pos_args[0]); 295 | 296 | // get the buffer to write the data from 297 | mp_buffer_info_t bufinfo; 298 | mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); 299 | 300 | // create the buffer to send memory address 301 | uint8_t buf_memaddr[MAX_MEMADDR_SIZE]; 302 | size_t memaddr_len = 0; 303 | for (int16_t i = args[ARG_addrsize].u_int - 8; i >= 0; i -= 8) { 304 | buf_memaddr[memaddr_len++] = args[ARG_memaddr].u_int >> i; 305 | } 306 | 307 | // do the transfer 308 | i2c_set_slave(self->i2c, args[ARG_addr].u_int); 309 | 310 | int ret = i2c_write(self->i2c, buf_memaddr, memaddr_len, false); 311 | if (ret < 0) { 312 | i2c_clear_fifo(self->i2c); 313 | mp_raise_OSError(-ret); 314 | } 315 | 316 | ret = i2c_write(self->i2c, bufinfo.buf, bufinfo.len, true); 317 | if (ret < 0) { 318 | i2c_clear_fifo(self->i2c); 319 | mp_raise_OSError(-ret); 320 | } 321 | 322 | return mp_const_none; 323 | } 324 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); 325 | 326 | STATIC const mp_rom_map_elem_t machine_i2c_locals_table[] = { 327 | // instance methods 328 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) }, 329 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2c_deinit_obj) }, 330 | { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, 331 | { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, 332 | { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, 333 | { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, 334 | { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, 335 | { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, 336 | { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, 337 | }; 338 | STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals, machine_i2c_locals_table); 339 | 340 | const mp_obj_type_t machine_i2c_type = { 341 | { &mp_type_type }, 342 | .name = MP_QSTR_I2C, 343 | .print = machine_i2c_print, 344 | .make_new = machine_i2c_make_new, 345 | .locals_dict = (mp_obj_t) &machine_i2c_locals, 346 | }; 347 | 348 | -------------------------------------------------------------------------------- /raspberrypi/machine_pin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "py/runtime.h" 6 | #include "py/mphal.h" 7 | #include "bcm283x_gpio.h" 8 | #include "modmachine.h" 9 | #include "extmod/virtpin.h" 10 | #include "machine_pin_util.h" 11 | 12 | typedef struct _machine_pin_obj_t { 13 | const mp_obj_base_t base; 14 | const uint32_t id; 15 | uint32_t pull_mode; // to save pull up/down settings 16 | } machine_pin_obj_t; 17 | 18 | STATIC machine_pin_obj_t machine_pin_obj[] = { 19 | {{&machine_pin_type}, 0, 0}, 20 | {{&machine_pin_type}, 1, 0}, 21 | {{&machine_pin_type}, 2, 0}, 22 | {{&machine_pin_type}, 3, 0}, 23 | {{&machine_pin_type}, 4, 0}, 24 | {{&machine_pin_type}, 5, 0}, 25 | {{&machine_pin_type}, 6, 0}, 26 | {{&machine_pin_type}, 7, 0}, 27 | {{&machine_pin_type}, 8, 0}, 28 | {{&machine_pin_type}, 9, 0}, 29 | {{&machine_pin_type}, 10, 0}, 30 | {{&machine_pin_type}, 11, 0}, 31 | {{&machine_pin_type}, 12, 0}, 32 | {{&machine_pin_type}, 13, 0}, 33 | {{&machine_pin_type}, 14, 0}, 34 | {{&machine_pin_type}, 15, 0}, 35 | {{&machine_pin_type}, 16, 0}, 36 | {{&machine_pin_type}, 17, 0}, 37 | {{&machine_pin_type}, 18, 0}, 38 | {{&machine_pin_type}, 19, 0}, 39 | {{&machine_pin_type}, 20, 0}, 40 | {{&machine_pin_type}, 21, 0}, 41 | {{&machine_pin_type}, 22, 0}, 42 | {{&machine_pin_type}, 23, 0}, 43 | {{&machine_pin_type}, 24, 0}, 44 | {{&machine_pin_type}, 25, 0}, 45 | {{&machine_pin_type}, 26, 0}, 46 | {{&machine_pin_type}, 27, 0}, 47 | {{&machine_pin_type}, 28, 0}, 48 | {{&machine_pin_type}, 29, 0}, 49 | {{&machine_pin_type}, 30, 0}, 50 | {{&machine_pin_type}, 31, 0}, 51 | {{&machine_pin_type}, 32, 0}, 52 | {{&machine_pin_type}, 33, 0}, 53 | {{&machine_pin_type}, 34, 0}, 54 | {{&machine_pin_type}, 35, 0}, 55 | {{&machine_pin_type}, 36, 0}, 56 | {{&machine_pin_type}, 37, 0}, 57 | {{&machine_pin_type}, 38, 0}, 58 | {{&machine_pin_type}, 39, 0}, 59 | {{&machine_pin_type}, 40, 0}, 60 | {{&machine_pin_type}, 41, 0}, 61 | {{&machine_pin_type}, 42, 0}, 62 | {{&machine_pin_type}, 43, 0}, 63 | {{&machine_pin_type}, 44, 0}, 64 | {{&machine_pin_type}, 45, 0}, 65 | {{&machine_pin_type}, 46, 0}, 66 | {{&machine_pin_type}, 47, 0}, 67 | {{&machine_pin_type}, 48, 0}, 68 | {{&machine_pin_type}, 49, 0}, 69 | {{&machine_pin_type}, 50, 0}, 70 | {{&machine_pin_type}, 51, 0}, 71 | {{&machine_pin_type}, 52, 0}, 72 | {{&machine_pin_type}, 53, 0}, 73 | }; 74 | 75 | int32_t pin_get_id(mp_obj_t *pin) { 76 | if (MP_OBJ_IS_TYPE(pin, &machine_pin_type)) { 77 | return ((machine_pin_obj_t *) pin)->id; 78 | } else { 79 | return -1; 80 | } 81 | } 82 | 83 | static void pin_set_pull_mode(uint32_t pin, uint32_t pud) { 84 | gpio_set_pull_mode(pin, pud); 85 | machine_pin_obj[pin].pull_mode = pud; 86 | } 87 | 88 | // Reading back the pull up/down settings is impossible for BCM2835. 89 | static uint32_t pin_get_pull_mode(uint32_t pin) { 90 | return machine_pin_obj[pin].pull_mode; 91 | } 92 | 93 | STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { 94 | machine_pin_obj_t *self = self_in; 95 | mp_printf(print, "Pin(%u", self->id); 96 | uint32_t mode = gpio_get_mode(self->id); 97 | qstr mode_qst = MP_QSTR_IN; 98 | if (mode == GPF_OUTPUT) { 99 | mode_qst = MP_QSTR_OUT; 100 | } 101 | mp_printf(print, ", mode=Pin.%s", qstr_str(mode_qst)); 102 | if (mode == GPF_INPUT) { 103 | uint32_t pull = pin_get_pull_mode(self->id); 104 | qstr pull_qst = MP_QSTR_PULL_NONE; 105 | if (pull == GPPUD_EN_UP) { 106 | pull_qst = MP_QSTR_PULL_UP; 107 | } else if (pull == GPPUD_EN_DOWN) { 108 | pull_qst = MP_QSTR_PULL_DOWN; 109 | } 110 | mp_printf(print, ", pull=Pin.%s", qstr_str(pull_qst)); 111 | } 112 | mp_printf(print, ")"); 113 | } 114 | 115 | // pin.init(mode, pull=None, *, value) 116 | STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 117 | enum { ARG_mode, ARG_pull, ARG_value }; 118 | static const mp_arg_t allowed_args[] = { 119 | { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}}, 120 | { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, 121 | { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, 122 | }; 123 | 124 | // parse args 125 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 126 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 127 | 128 | // set initial value (do this before configuring mode/pull) 129 | if (args[ARG_value].u_obj != MP_OBJ_NULL) { 130 | gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); 131 | } 132 | 133 | // configure mode 134 | if (args[ARG_mode].u_obj != mp_const_none) { 135 | mp_int_t pin_io_mode = mp_obj_get_int(args[ARG_mode].u_obj); 136 | if (self->id > 53) { 137 | mp_raise_ValueError("pin not found"); 138 | } else { 139 | gpio_set_mode(self->id, pin_io_mode); 140 | } 141 | } 142 | 143 | // configure pull 144 | if (args[ARG_pull].u_obj != mp_const_none) { 145 | pin_set_pull_mode(self->id, mp_obj_get_int(args[ARG_pull].u_obj)); 146 | } 147 | 148 | return mp_const_none; 149 | } 150 | 151 | // constructor(id, ...) 152 | mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { 153 | mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); 154 | 155 | // get the wanted pin object 156 | int wanted_pin = mp_obj_get_int(args[0]); 157 | const machine_pin_obj_t *self = NULL; 158 | if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) { 159 | self = (machine_pin_obj_t*)&machine_pin_obj[wanted_pin]; 160 | } else { 161 | mp_raise_ValueError("invalid pin"); 162 | } 163 | 164 | if (n_args > 1 || n_kw > 0) { 165 | // pin mode given, so configure this GPIO 166 | mp_map_t kw_args; 167 | mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); 168 | machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); 169 | } 170 | 171 | return MP_OBJ_FROM_PTR(self); 172 | } 173 | 174 | // fast method for getting/setting pin value 175 | STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { 176 | mp_arg_check_num(n_args, n_kw, 0, 1, false); 177 | machine_pin_obj_t *self = self_in; 178 | if (n_args == 0) { 179 | // get pin 180 | return MP_OBJ_NEW_SMALL_INT(gpio_get_level(self->id)); 181 | } else { 182 | // set pin 183 | gpio_set_level(self->id, mp_obj_is_true(args[0])); 184 | return mp_const_none; 185 | } 186 | } 187 | 188 | // pin.init(mode, pull) 189 | STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { 190 | return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); 191 | } 192 | MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); 193 | 194 | // pin.value([value]) 195 | STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { 196 | return machine_pin_call(args[0], n_args - 1, 0, args + 1); 197 | } 198 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); 199 | 200 | 201 | STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { 202 | (void)errcode; 203 | machine_pin_obj_t *self = self_in; 204 | 205 | switch (request) { 206 | case MP_PIN_READ: { 207 | return gpio_get_level(self->id); 208 | } 209 | case MP_PIN_WRITE: { 210 | gpio_set_level(self->id, arg); 211 | return 0; 212 | } 213 | } 214 | return -1; 215 | } 216 | 217 | STATIC const mp_pin_p_t pin_pin_p = { 218 | .ioctl = pin_ioctl, 219 | }; 220 | 221 | STATIC const mp_rom_map_elem_t machine_pin_locals_table[] = { 222 | // instance methods 223 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, 224 | { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, 225 | 226 | // class constants 227 | { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPF_INPUT) }, 228 | { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPF_OUTPUT) }, 229 | { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPPUD_NONE) }, 230 | { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPPUD_EN_UP) }, 231 | { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPPUD_EN_DOWN) }, 232 | }; 233 | STATIC MP_DEFINE_CONST_DICT(machine_pin_locals, machine_pin_locals_table); 234 | 235 | const mp_obj_type_t machine_pin_type = { 236 | { &mp_type_type }, 237 | .name = MP_QSTR_Pin, 238 | .print = machine_pin_print, 239 | .make_new = mp_pin_make_new, 240 | .call = machine_pin_call, 241 | .protocol = &pin_pin_p, 242 | .locals_dict = (mp_obj_t)&machine_pin_locals, 243 | }; 244 | 245 | -------------------------------------------------------------------------------- /raspberrypi/machine_pin_util.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_MACHINE_PIN_UTIL_H 2 | #define MICROPY_INCLUDED_RPI_MACHINE_PIN_UTIL_H 3 | 4 | int32_t pin_get_id(mp_obj_t *pin); 5 | 6 | #endif // MICROPY_INCLUDED_RPI_MACHINE_PIN_UTIL_H 7 | -------------------------------------------------------------------------------- /raspberrypi/machine_sdcard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/runtime.h" 5 | #include "py/mphal.h" 6 | #include "lib/oofatfs/ff.h" 7 | #include "extmod/vfs_fat.h" 8 | 9 | #include "sd.h" 10 | #include "modmachine.h" 11 | 12 | /******************************************************************************/ 13 | // MicroPython bindings 14 | // 15 | // Expose the SD card as an object with the block protocol. 16 | 17 | // there is a singleton SDCard object 18 | const mp_obj_base_t machine_sdcard_obj = {&machine_sdcard_type}; 19 | 20 | STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { 21 | // check arguments 22 | mp_arg_check_num(n_args, n_kw, 0, 0, false); 23 | 24 | // return singleton object 25 | return (mp_obj_t)&machine_sdcard_obj; 26 | } 27 | 28 | STATIC mp_obj_t machine_sdcard_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { 29 | mp_buffer_info_t bufinfo; 30 | mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); 31 | mp_uint_t ret = sd_readblock(mp_obj_get_int(block_num), bufinfo.buf, bufinfo.len / SDCARD_BLOCK_SIZE); 32 | return mp_obj_new_bool(ret == 0); 33 | } 34 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_readblocks_obj, machine_sdcard_readblocks); 35 | 36 | STATIC mp_obj_t machine_sdcard_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { 37 | mp_buffer_info_t bufinfo; 38 | mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); 39 | mp_uint_t ret = sd_writeblock(mp_obj_get_int(block_num), bufinfo.buf, bufinfo.len / SDCARD_BLOCK_SIZE); 40 | return mp_obj_new_bool(ret == 0); 41 | } 42 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_writeblocks_obj, machine_sdcard_writeblocks); 43 | 44 | /* 45 | // sector read/write test method 46 | // danger!! this method writes new data to lba=0xbb00 47 | void print_buf(unsigned char *buf) { 48 | for(int l=0; l < 4; l++) { 49 | for(int x=0; x < 16; x++) { 50 | printf("%02x ", buf[l*16+x]); 51 | } 52 | printf(" "); 53 | for(int x=0; x < 16; x++) { 54 | unsigned char c = buf[l*16+x]; 55 | if ((c < 0x20) || (c == 0x7f)) { 56 | c = '.'; 57 | } 58 | printf("%c", c); 59 | } 60 | printf("\n"); 61 | } 62 | printf("\n"); 63 | } 64 | 65 | STATIC mp_obj_t machine_sdcard_test(mp_obj_t self) { 66 | unsigned char bufsave[512]; 67 | unsigned char bufw[512]; 68 | unsigned char bufr[512]; 69 | int ret; 70 | for(int i = 0; i < 512; i++) { 71 | bufr[i] = 0; 72 | bufw[i] = 0x20 + (i % 64); 73 | } 74 | ret = sd_readblock(0xbb00, bufsave, 1); 75 | printf("result=%d\n", ret); 76 | print_buf(bufsave); 77 | 78 | ret = sd_writeblock(0xbb00, bufw, 1); 79 | printf("result=%d\n", ret); 80 | print_buf(bufw); 81 | ret = sd_readblock(0xbb00, bufr, 1); 82 | printf("result=%d\n", ret); 83 | print_buf(bufr); 84 | 85 | ret = sd_writeblock(0xbb00, bufsave, 1); 86 | printf("result=%d\n", ret); 87 | ret = sd_readblock(0xbb00, bufr, 1); 88 | printf("result=%d\n", ret); 89 | print_buf(bufr); 90 | 91 | return mp_const_none; 92 | } 93 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_sdcard_test_obj, machine_sdcard_test); 94 | */ 95 | 96 | STATIC mp_obj_t machine_sdcard_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { 97 | mp_int_t cmd = mp_obj_get_int(cmd_in); 98 | switch (cmd) { 99 | case BP_IOCTL_INIT: 100 | if (sd_init() != SD_OK) { 101 | return MP_OBJ_NEW_SMALL_INT(-1); // error 102 | } 103 | return MP_OBJ_NEW_SMALL_INT(0); // success 104 | 105 | case BP_IOCTL_DEINIT: 106 | // nothing to do 107 | return MP_OBJ_NEW_SMALL_INT(0); // success 108 | 109 | case BP_IOCTL_SYNC: 110 | // nothing to do 111 | return MP_OBJ_NEW_SMALL_INT(0); // success 112 | 113 | case BP_IOCTL_SEC_COUNT: 114 | // nothing to do 115 | return MP_OBJ_NEW_SMALL_INT(-1); // error 116 | // return MP_OBJ_NEW_SMALL_INT(sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE); 117 | 118 | case BP_IOCTL_SEC_SIZE: 119 | return MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE); 120 | 121 | default: // unknown command 122 | return MP_OBJ_NEW_SMALL_INT(-1); // error 123 | } 124 | } 125 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_ioctl_obj, machine_sdcard_ioctl); 126 | 127 | STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = { 128 | // block device protocol 129 | { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&machine_sdcard_readblocks_obj) }, 130 | { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&machine_sdcard_writeblocks_obj) }, 131 | { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&machine_sdcard_ioctl_obj) }, 132 | // { MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&machine_sdcard_test_obj) }, 133 | }; 134 | 135 | STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table); 136 | 137 | const mp_obj_type_t machine_sdcard_type = { 138 | { &mp_type_type }, 139 | .name = MP_QSTR_SDCard, 140 | .make_new = machine_sdcard_make_new, 141 | .locals_dict = (mp_obj_dict_t*)&machine_sdcard_locals_dict, 142 | }; 143 | 144 | void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { 145 | vfs->base.type = &mp_fat_vfs_type; 146 | vfs->flags |= FSUSER_HAVE_IOCTL; 147 | vfs->fatfs.drv = vfs; 148 | vfs->fatfs.part = part; 149 | vfs->readblocks[0] = (mp_obj_t)&machine_sdcard_readblocks_obj; 150 | vfs->readblocks[1] = (mp_obj_t)&machine_sdcard_obj; 151 | // vfs->readblocks[2] = (mp_obj_t)sdcard_read_blocks; // native version 152 | vfs->writeblocks[0] = (mp_obj_t)&machine_sdcard_writeblocks_obj; 153 | vfs->writeblocks[1] = (mp_obj_t)&machine_sdcard_obj; 154 | // vfs->writeblocks[2] = (mp_obj_t)sdcard_write_blocks; // native version 155 | vfs->u.ioctl[0] = (mp_obj_t)&machine_sdcard_ioctl_obj; 156 | vfs->u.ioctl[1] = (mp_obj_t)&machine_sdcard_obj; 157 | } 158 | 159 | -------------------------------------------------------------------------------- /raspberrypi/machine_spi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "py/runtime.h" 6 | #include "py/mphal.h" 7 | #include "py/mperrno.h" 8 | #include "bcm283x_gpio.h" 9 | #include "bcm283x_spi.h" 10 | #include "rpi.h" 11 | #include "spi.h" 12 | #include "modmachine.h" 13 | 14 | #define MICROPY_PY_MACHINE_SPI_MSB (0) 15 | #define MICROPY_PY_MACHINE_SPI_LSB (1) 16 | #define SPI_DEFAULT_CLK (1000000) 17 | 18 | typedef struct _machine_spi_obj_t { 19 | mp_obj_base_t base; 20 | uint32_t id; 21 | spi_t *spi; 22 | } machine_spi_obj_t; 23 | 24 | const machine_spi_obj_t machine_spi_obj[] = { 25 | {{&machine_spi_type}, 0, (spi_t *) SPI0}, 26 | }; 27 | 28 | static void spi_gpio_setup(uint32_t id, bool on) { 29 | if (on) { 30 | switch(id) { 31 | case 0: 32 | gpio_set_mode(9, GPF_ALT_0); // SPI0_MISO 33 | gpio_set_mode(10, GPF_ALT_0); // SPI0_MOSI 34 | gpio_set_mode(11, GPF_ALT_0); // SPI0_SCLK 35 | break; 36 | default: 37 | ; 38 | } 39 | } else { 40 | switch(id) { 41 | case 0: 42 | gpio_set_mode(9, GPF_INPUT); 43 | gpio_set_mode(10, GPF_INPUT); 44 | gpio_set_mode(11, GPF_INPUT); 45 | break; 46 | default: 47 | ; 48 | } 49 | } 50 | } 51 | 52 | enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; 53 | static const mp_arg_t allowed_args[] = { 54 | { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_DEFAULT_CLK} }, 55 | { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 56 | { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 57 | { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, 58 | { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, 59 | }; 60 | 61 | STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { 62 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 63 | 64 | // parse args 65 | int id = mp_obj_get_int(all_args[0]); 66 | if (id != 0) { 67 | mp_raise_ValueError("invalid bus number"); 68 | } 69 | 70 | mp_arg_parse_all_kw_array(--n_args, n_kw, ++all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 71 | 72 | machine_spi_obj_t *spi = (machine_spi_obj_t*) &machine_spi_obj[id]; 73 | 74 | if (args[ARG_bits].u_int != 8) { 75 | mp_raise_ValueError("bits must be 8"); 76 | } 77 | if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) { 78 | mp_raise_ValueError("firstbit must be MSB"); 79 | } 80 | 81 | // set up GPIO alternate function 82 | spi_gpio_setup(id, true); 83 | 84 | // initialize SPI controller 85 | spi_init(spi->spi, args[ARG_polarity].u_int, args[ARG_phase].u_int); 86 | spi_set_clock_speed(spi->spi, args[ARG_baudrate].u_int); 87 | 88 | return spi; 89 | } 90 | 91 | STATIC mp_obj_t machine_spi_init_helper(machine_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 92 | // parse args 93 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 94 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 95 | 96 | // set up GPIO alternate function 97 | spi_gpio_setup(self->id, true); 98 | 99 | // initialize SPI controller 100 | if (args[ARG_bits].u_int != 8) { 101 | mp_raise_ValueError("bits must be 8"); 102 | } 103 | if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) { 104 | mp_raise_ValueError("firstbit must be MSB"); 105 | } 106 | spi_init(self->spi, args[ARG_polarity].u_int, args[ARG_phase].u_int); 107 | spi_set_clock_speed(self->spi, args[ARG_baudrate].u_int); 108 | 109 | return mp_const_none; 110 | } 111 | 112 | STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { 113 | return machine_spi_init_helper(args[0], n_args - 1, args + 1, kw_args); 114 | } 115 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 0, machine_spi_init); 116 | 117 | STATIC mp_obj_t machine_spi_deinit(mp_obj_t self_in) { 118 | machine_spi_obj_t *self = self_in; 119 | 120 | // de-initialize SPI controller 121 | spi_deinit(self->spi); 122 | 123 | // set GPIO to input mode 124 | spi_gpio_setup(self->id, false); 125 | 126 | return mp_const_none; 127 | } 128 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); 129 | 130 | STATIC void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { 131 | machine_spi_obj_t *self = self_in; 132 | spi_t *spi = (spi_t *) self->spi; 133 | uint32_t baudrate = spi_get_clock_speed(spi); 134 | uint32_t polarity = spi->CS & CS_CPOL; 135 | uint32_t phase = spi->CS & CS_CPHA; 136 | 137 | mp_printf(print, "SPI(%u", self->id); 138 | if (baudrate != SPI_DEFAULT_CLK) { 139 | mp_printf(print, ", baudrate=%u", baudrate); 140 | } 141 | if (polarity) { 142 | mp_printf(print, ", polarity=1"); 143 | } 144 | if (phase) { 145 | mp_printf(print, ", phase=1"); 146 | } 147 | mp_printf(print, ")"); 148 | } 149 | 150 | STATIC mp_obj_t machine_spi_write(mp_obj_t self_in, mp_obj_t buf) { 151 | machine_spi_obj_t *self = (machine_spi_obj_t*) MP_OBJ_TO_PTR(self_in); 152 | mp_buffer_info_t bufinfo; 153 | mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); 154 | int ret = spi_transfer(self->spi, bufinfo.buf, bufinfo.len, NULL, 0, 0); 155 | if (ret < 0) { 156 | mp_raise_OSError(-ret); 157 | } 158 | 159 | return MP_OBJ_NEW_SMALL_INT(ret); 160 | } 161 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_spi_write_obj, machine_spi_write); 162 | 163 | STATIC mp_obj_t machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wbuf, mp_obj_t rbuf) { 164 | machine_spi_obj_t *self = (machine_spi_obj_t*) MP_OBJ_TO_PTR(self_in); 165 | mp_buffer_info_t src; 166 | mp_get_buffer_raise(wbuf, &src, MP_BUFFER_READ); 167 | mp_buffer_info_t dest; 168 | mp_get_buffer_raise(rbuf, &dest, MP_BUFFER_WRITE); 169 | if (src.len != dest.len) { 170 | mp_raise_ValueError("buffers must be the same length"); 171 | } 172 | if (src.len > 0) { 173 | int ret = spi_transfer(self->spi, src.buf, src.len, dest.buf, dest.len, 0); 174 | if (ret < 0) { 175 | mp_raise_OSError(-ret); 176 | } 177 | } 178 | return mp_const_none; 179 | } 180 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_spi_write_readinto_obj, machine_spi_write_readinto); 181 | 182 | STATIC mp_obj_t machine_spi_readinto(size_t n_args, const mp_obj_t *args) { 183 | machine_spi_obj_t *self = (machine_spi_obj_t*) MP_OBJ_TO_PTR(args[0]); 184 | mp_buffer_info_t bufinfo; 185 | mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); 186 | if (bufinfo.len > 0) { 187 | uint8_t wchar = (n_args == 2) ? 0 : mp_obj_get_int(args[2]); 188 | int ret = spi_transfer(self->spi, NULL, 0, (uint8_t*)bufinfo.buf, bufinfo.len, wchar); 189 | if (ret < 0) { 190 | mp_raise_OSError(-ret); 191 | } 192 | } 193 | return mp_const_none; 194 | } 195 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_spi_readinto_obj, 1, 2, machine_spi_readinto); 196 | 197 | STATIC mp_obj_t machine_spi_read(size_t n_args, const mp_obj_t *args) { 198 | machine_spi_obj_t *self = (machine_spi_obj_t*) MP_OBJ_TO_PTR(args[0]); 199 | vstr_t vstr; 200 | vstr_init_len(&vstr, mp_obj_get_int(args[1])); 201 | if (vstr.len > 0) { 202 | uint8_t wchar = (n_args == 2) ? 0 : mp_obj_get_int(args[2]); 203 | int ret = spi_transfer(self->spi, NULL, 0, (uint8_t*)vstr.buf, vstr.len, wchar); 204 | if (ret < 0) { 205 | mp_raise_OSError(-ret); 206 | } 207 | } 208 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 209 | } 210 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_spi_read_obj, 1, 2, machine_spi_read); 211 | 212 | STATIC const mp_rom_map_elem_t machine_spi_locals_table[] = { 213 | // instance methods 214 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_spi_init_obj) }, 215 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, 216 | { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_spi_write_obj) }, 217 | { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&machine_spi_write_readinto_obj) }, 218 | { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_spi_read_obj) }, 219 | { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_spi_readinto_obj) }, 220 | // class constants 221 | { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) }, 222 | { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) }, 223 | }; 224 | STATIC MP_DEFINE_CONST_DICT(machine_spi_locals, machine_spi_locals_table); 225 | 226 | const mp_obj_type_t machine_spi_type = { 227 | { &mp_type_type }, 228 | .name = MP_QSTR_SPI, 229 | .print = machine_spi_print, 230 | .make_new = machine_spi_make_new, 231 | .locals_dict = (mp_obj_t) &machine_spi_locals, 232 | }; 233 | 234 | -------------------------------------------------------------------------------- /raspberrypi/machine_timer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "py/runtime.h" 6 | #include "py/mphal.h" 7 | #include "modmachine.h" 8 | #include "rpi.h" 9 | #include "bcm283x_it.h" 10 | 11 | /* 12 | if mode of a timer is FREE, MicroPython will 13 | never change the timer compare register. 14 | (But it would be updated by VCORE.) 15 | */ 16 | typedef enum _timer_mode_t { 17 | ONE_SHOT = 0, 18 | PERIODIC = 1, 19 | FREE = 2, 20 | } timer_mode_t; 21 | 22 | typedef struct _machine_timer_obj_t { 23 | const mp_obj_base_t base; 24 | const uint32_t id; 25 | bool active; 26 | uint32_t counter; 27 | uint32_t period; 28 | timer_mode_t mode; 29 | mp_obj_t callback; 30 | } machine_timer_obj_t; 31 | 32 | static machine_timer_obj_t machine_timer_obj[] = { 33 | {{&machine_timer_type}, 0, true, 0, 0, FREE, NULL}, 34 | {{&machine_timer_type}, 1, false, 0, 0, PERIODIC, NULL}, 35 | {{&machine_timer_type}, 2, true, 0, 0, FREE, NULL}, 36 | {{&machine_timer_type}, 3, false, 0, 0, PERIODIC, NULL}, 37 | }; 38 | 39 | static void timer_enable(const int num) { 40 | if ((IRQ_ENABLE1 & IRQ_SYSTIMER(num)) == 0) { 41 | machine_timer_obj[num].active = true; 42 | if (machine_timer_obj[num].mode != FREE) { 43 | systimer->C[num] = systimer->CLO + machine_timer_obj[num].period; 44 | } 45 | systimer->CS |= (1 << num); 46 | IRQ_ENABLE1 = IRQ_SYSTIMER(num); 47 | } 48 | } 49 | 50 | static void timer_disable(const int num) { 51 | IRQ_DISABLE1 = IRQ_SYSTIMER(num); 52 | machine_timer_obj[num].active = false; 53 | } 54 | 55 | void isr_irq_timer(void) { 56 | int timer_value; 57 | 58 | if (IRQ_PEND1 & IRQ_SYSTIMER(0)) { 59 | timer_value = systimer->C[0]; 60 | } else if (IRQ_PEND1 & IRQ_SYSTIMER(1)) { 61 | timer_value = systimer->C[1]; 62 | } else if (IRQ_PEND1 & IRQ_SYSTIMER(2)) { 63 | timer_value = systimer->C[2]; 64 | } else if (IRQ_PEND1 & IRQ_SYSTIMER(3)) { 65 | timer_value = systimer->C[3]; 66 | } else { 67 | return; 68 | } 69 | /* schedule callback func for timers which value == timer_value */ 70 | machine_timer_obj_t *tim = &machine_timer_obj[0]; 71 | for (int i = 0; i < 4; i++) { 72 | if (timer_value == systimer->C[i]) { 73 | if (tim[i].active) { 74 | tim[i].counter++; 75 | if (tim[i].callback != mp_const_none) { 76 | mp_sched_schedule(tim[i].callback, &tim[i]); 77 | } 78 | if (tim[i].mode == PERIODIC) { 79 | systimer->C[i] += tim[i].period; 80 | } else if (tim[i].mode == ONE_SHOT) { 81 | timer_disable(i); 82 | } else { 83 | // FREE mode 84 | tim[i].period = systimer->C[i]; 85 | } 86 | } 87 | systimer->CS |= (1 << i); 88 | } 89 | } 90 | } 91 | 92 | STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 93 | static const mp_arg_t allowed_args[] = { 94 | { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, 95 | { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = (int) PERIODIC} }, 96 | { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 97 | }; 98 | 99 | // parse args 100 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 101 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 102 | 103 | self->period = args[0].u_int; 104 | self->mode = args[1].u_int; 105 | self->callback = args[2].u_obj; 106 | self->counter = 0; 107 | 108 | // the timer is not enabled in this function 109 | 110 | return mp_const_none; 111 | } 112 | 113 | STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { 114 | mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); 115 | int id = mp_obj_get_int(args[0]); 116 | if (id > 3) { 117 | mp_raise_ValueError("invalid timer number"); 118 | } 119 | machine_timer_obj_t *tim = (machine_timer_obj_t*) &machine_timer_obj[id]; 120 | 121 | mp_map_t kw_args; 122 | mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); 123 | machine_timer_init_helper(tim, n_args - 1, args + 1, &kw_args); 124 | 125 | // the timer is enabled when the args other than id are provided 126 | if (n_kw > 0) { 127 | timer_enable(id); 128 | } 129 | 130 | return tim; 131 | } 132 | 133 | STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { 134 | machine_timer_obj_t *self = (machine_timer_obj_t*) args[0]; 135 | machine_timer_init_helper(self, n_args - 1, args + 1, kw_args); 136 | timer_enable(self->id); 137 | return mp_const_none; 138 | } 139 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 0, machine_timer_init); 140 | 141 | STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { 142 | machine_timer_obj_t *self = self_in; 143 | timer_disable(self->id); 144 | return mp_const_none; 145 | } 146 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); 147 | 148 | STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { 149 | machine_timer_obj_t *self = self_in; 150 | mp_printf(print, "Timer(%u, period=%u", self->id, self->period); 151 | qstr mode_qstr = MP_QSTR_ONE_SHOT; 152 | if (self->mode == PERIODIC) { 153 | mode_qstr = MP_QSTR_PERIODIC; 154 | } else if (self->mode == FREE) { 155 | mode_qstr = MP_QSTR_FREE; 156 | } 157 | mp_printf(print, ", mode=Timer.%s", qstr_str(mode_qstr)); 158 | mp_printf(print, ", counter=%u)", self->counter); 159 | mp_printf(print, " # compare=%u", systimer->C[self->id]); 160 | if (!self->active) { 161 | mp_printf(print, "; inactive"); 162 | } 163 | } 164 | 165 | /// \method counter([value]) 166 | /// Get or set the timer counter. 167 | STATIC mp_obj_t machine_timer_counter(size_t n_args, const mp_obj_t *args) { 168 | machine_timer_obj_t *self = args[0]; 169 | if (n_args == 1) { 170 | // get 171 | return mp_obj_new_int(self->counter); 172 | } else { 173 | // set 174 | self->counter = mp_obj_get_int(args[1]); 175 | return mp_const_none; 176 | } 177 | } 178 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_counter_obj, 1, 2, machine_timer_counter); 179 | 180 | /// \method period([value]) 181 | /// Get or set the period of the timer. 182 | STATIC mp_obj_t machine_timer_period(size_t n_args, const mp_obj_t *args) { 183 | machine_timer_obj_t *self = args[0]; 184 | if (n_args == 1) { 185 | // get 186 | return mp_obj_new_int_from_uint(self->period); 187 | } else { 188 | // set 189 | self->period = mp_obj_get_int(args[1]); 190 | return mp_const_none; 191 | } 192 | } 193 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_period_obj, 1, 2, machine_timer_period); 194 | 195 | /// \method callback(fun) 196 | /// Set the function to be called when the timer triggers. 197 | /// `fun` is passed 1 argument, the timer object. 198 | STATIC mp_obj_t machine_timer_callback(mp_obj_t self_in, mp_obj_t callback) { 199 | machine_timer_obj_t *self = self_in; 200 | if (callback == mp_const_none) { 201 | self->callback = mp_const_none; 202 | } else if (mp_obj_is_callable(callback)) { 203 | self->callback = callback; 204 | } else { 205 | mp_raise_ValueError("callback must be None or a callable object"); 206 | } 207 | return mp_const_none; 208 | } 209 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_timer_callback_obj, machine_timer_callback); 210 | 211 | /// \method compare_register([value]) 212 | /// Get or set the timer's current compare register value. 213 | STATIC mp_obj_t machine_timer_compare_register(size_t n_args, const mp_obj_t *args) { 214 | machine_timer_obj_t *self = args[0]; 215 | if (n_args == 1) { 216 | // get 217 | return mp_obj_new_int_from_uint(systimer->C[self->id]); 218 | } else { 219 | // set 220 | systimer->C[self->id] = mp_obj_get_int(args[1]); 221 | return mp_const_none; 222 | } 223 | } 224 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_timer_compare_register_obj, 1, 2, machine_timer_compare_register); 225 | 226 | STATIC const mp_rom_map_elem_t machine_timer_locals_table[] = { 227 | // instance methods 228 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, 229 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, 230 | { MP_ROM_QSTR(MP_QSTR_counter), MP_ROM_PTR(&machine_timer_counter_obj) }, 231 | { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&machine_timer_period_obj) }, 232 | { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&machine_timer_callback_obj) }, 233 | { MP_ROM_QSTR(MP_QSTR_compare_register), MP_ROM_PTR(&machine_timer_compare_register_obj) }, 234 | 235 | // class constants 236 | { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT((int) ONE_SHOT) }, 237 | { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT((int) PERIODIC) }, 238 | { MP_ROM_QSTR(MP_QSTR_FREE), MP_ROM_INT((int) FREE) }, 239 | }; 240 | STATIC MP_DEFINE_CONST_DICT(machine_timer_locals, machine_timer_locals_table); 241 | 242 | const mp_obj_type_t machine_timer_type = { 243 | { &mp_type_type }, 244 | .name = MP_QSTR_Timer, 245 | .print = machine_timer_print, 246 | .make_new = machine_timer_make_new, 247 | .locals_dict = (mp_obj_t) &machine_timer_locals, 248 | }; 249 | 250 | -------------------------------------------------------------------------------- /raspberrypi/machine_usb_mode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/runtime.h" 5 | #include "machine_usb_mode.h" 6 | #include "usbhost.h" 7 | 8 | 9 | // this will be persistent across a soft-reset 10 | mp_uint_t rpi_usb_flags = 0; 11 | 12 | STATIC mp_obj_t machine_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 13 | static const mp_arg_t allowed_args[] = { 14 | { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, 15 | }; 16 | 17 | // fetch the current usb mode -> machine.usb_mode() 18 | if (n_args == 0) { 19 | return MP_OBJ_NEW_QSTR(MP_QSTR_host); 20 | } 21 | 22 | // parse args 23 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 24 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 25 | 26 | // record the fact that the usb has been explicitly configured 27 | rpi_usb_flags |= RPI_USB_FLAG_USB_MODE_CALLED; 28 | 29 | // check if user wants to disable the USB 30 | if (args[0].u_obj == mp_const_none) { 31 | // disable usb 32 | rpi_usb_host_deinit(); 33 | return mp_const_none; 34 | } 35 | 36 | // get mode string 37 | const char *mode_str = mp_obj_str_get_str(args[0].u_obj); 38 | 39 | // hardware configured for USB host mode 40 | 41 | if (strcmp(mode_str, "host") == 0) { 42 | rpi_usb_host_init(); 43 | } else { 44 | goto bad_mode; 45 | } 46 | 47 | return mp_const_none; 48 | 49 | bad_mode: 50 | mp_raise_ValueError("bad USB mode"); 51 | } 52 | MP_DEFINE_CONST_FUN_OBJ_KW(machine_usb_mode_obj, 0, machine_usb_mode); 53 | -------------------------------------------------------------------------------- /raspberrypi/machine_usb_mode.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_MACHINE_USBMODE_H 2 | #define MICROPY_INCLUDED_RPI_MACHINE_USBMODE_H 3 | 4 | #define RPI_USB_FLAG_USB_MODE_CALLED (0x0002) 5 | 6 | extern mp_uint_t rpi_usb_flags; 7 | 8 | MP_DECLARE_CONST_FUN_OBJ_KW(machine_usb_mode_obj); 9 | 10 | #endif // MICROPY_INCLUDED_RPI_MACHINE_USBMODE_H 11 | -------------------------------------------------------------------------------- /raspberrypi/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "py/nlr.h" 6 | #include "py/compile.h" 7 | #include "py/runtime.h" 8 | #include "py/stackctrl.h" 9 | #include "py/repl.h" 10 | #include "py/gc.h" 11 | #include "py/mperrno.h" 12 | #include "lib/utils/interrupt_char.h" 13 | #include "lib/utils/pyexec.h" 14 | 15 | #include "arm_exceptions.h" 16 | #include "rpi.h" 17 | #include "mphalport.h" 18 | #include "usbhost.h" 19 | 20 | #if MICROPY_MOUNT_SD_CARD 21 | 22 | #include "lib/oofatfs/ff.h" 23 | #include "extmod/vfs_fat.h" 24 | #include "sd.h" 25 | #include "modmachine.h" 26 | 27 | extern void sdcard_init_vfs(fs_user_mount_t *vfs, int part); 28 | 29 | #endif 30 | 31 | void clear_bss(void) { 32 | extern void * _bss_start; 33 | extern void * _bss_end; 34 | unsigned int *p; 35 | 36 | for(p = (unsigned int *)&_bss_start; p < (unsigned int *) &_bss_end; p++) { 37 | *p = 0; 38 | } 39 | } 40 | 41 | #define TAG_CMDLINE 0x54410009 42 | char *arm_boot_tag_cmdline(const int32_t *ptr) { 43 | int32_t datalen = *ptr; 44 | int32_t tag = *(ptr + 1); 45 | 46 | if (ptr != 0) { 47 | while(tag) { 48 | if (tag == TAG_CMDLINE) { 49 | return (char *) (ptr + 2); 50 | } else { 51 | ptr += datalen; 52 | datalen = *ptr; 53 | tag = *(ptr + 1); 54 | } 55 | } 56 | } 57 | return NULL; 58 | } 59 | 60 | #if MICROPY_MOUNT_SD_CARD 61 | 62 | STATIC bool init_sdcard_fs(void) { 63 | bool first_part = true; 64 | for (int part_num = 1; part_num <= 4; ++part_num) { 65 | // create vfs object 66 | fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); 67 | mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); 68 | if (vfs == NULL || vfs_fat == NULL) { 69 | printf("vfs=NULL\n"); 70 | break; 71 | } 72 | vfs_fat->flags = FSUSER_FREE_OBJ; 73 | sdcard_init_vfs(vfs_fat, part_num); 74 | 75 | // try to mount the partition 76 | FRESULT res = f_mount(&vfs_fat->fatfs); 77 | 78 | if (res != FR_OK) { 79 | // couldn't mount 80 | m_del_obj(fs_user_mount_t, vfs_fat); 81 | m_del_obj(mp_vfs_mount_t, vfs); 82 | } else { 83 | // mounted via FatFs, now mount the SD partition in the VFS 84 | if (first_part) { 85 | // the first available partition is traditionally called "sd" for simplicity 86 | vfs->str = "/sd"; 87 | vfs->len = 3; 88 | } else { 89 | // subsequent partitions are numbered by their index in the partition table 90 | if (part_num == 2) { 91 | vfs->str = "/sd2"; 92 | } else if (part_num == 2) { 93 | vfs->str = "/sd3"; 94 | } else { 95 | vfs->str = "/sd4"; 96 | } 97 | vfs->len = 4; 98 | } 99 | vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); 100 | vfs->next = NULL; 101 | for (mp_vfs_mount_t **m = &MP_STATE_VM(vfs_mount_table);; m = &(*m)->next) { 102 | if (*m == NULL) { 103 | *m = vfs; 104 | break; 105 | } 106 | } 107 | 108 | if (first_part) { 109 | // use SD card as current directory 110 | MP_STATE_PORT(vfs_cur) = vfs; 111 | } 112 | first_part = false; 113 | } 114 | } 115 | 116 | if (first_part) { 117 | printf("PYB: can't mount SD card\n"); 118 | return false; 119 | } else { 120 | return true; 121 | } 122 | } 123 | 124 | #endif 125 | 126 | int arm_main(uint32_t r0, uint32_t id, const int32_t *atag) { 127 | bool use_qemu = false; 128 | 129 | extern char * _heap_end; 130 | extern char * _heap_start; 131 | extern char * _estack; 132 | 133 | clear_bss(); 134 | mp_stack_set_top(&_estack); 135 | mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); 136 | 137 | // check ARM boot tag and set up standard I/O 138 | if (atag != (int32_t *) 0x100) { 139 | // atag points to 0x100 in general, so something may be wrong? 140 | atag = (int32_t *) 0x100; 141 | } 142 | if (atag && (strcmp("qemu", arm_boot_tag_cmdline(atag)) == 0)) { 143 | use_qemu = true; 144 | } 145 | 146 | if (use_qemu) { 147 | uart_init(UART_QEMU); 148 | } else { 149 | uart_init(MINI_UART); 150 | arm_irq_disable(); 151 | arm_exceptions_init(); 152 | arm_irq_enable(); 153 | rpi_init(); 154 | } 155 | 156 | // start MicroPython 157 | while (true) { 158 | gc_init (&_heap_start, &_heap_end ); 159 | mp_init(); 160 | mp_obj_list_init(mp_sys_path, 0); 161 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) 162 | mp_obj_list_init(mp_sys_argv, 0); 163 | mp_hal_stdout_tx_strn("\r\n", 2); 164 | 165 | #if MICROPY_MODULE_FROZEN_MPY 166 | pyexec_frozen_module("_boot.py"); 167 | #endif 168 | 169 | #if MICROPY_MOUNT_SD_CARD 170 | bool mounted_sdcard = false; 171 | if (!use_qemu) { 172 | printf("mounting SD card..."); 173 | mounted_sdcard = init_sdcard_fs(); 174 | if (mounted_sdcard) { 175 | printf("done\n\r"); 176 | } else { 177 | printf("failed\n\r"); 178 | } 179 | } 180 | 181 | if (!use_qemu && mounted_sdcard) { 182 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); 183 | mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); 184 | if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { 185 | mp_import_stat_t stat; 186 | // Run the boot config script from the current directory. 187 | const char boot_py[] = "boot.py"; 188 | stat = mp_import_stat(boot_py); 189 | if (stat == MP_IMPORT_STAT_FILE) { 190 | int ret = pyexec_file(boot_py); 191 | if (!ret) { 192 | printf("%s: execution error\n\r", boot_py); 193 | } 194 | } 195 | // Run the main script from the current directory. 196 | const char main_py[] = "main.py"; 197 | stat = mp_import_stat(main_py); 198 | if (stat == MP_IMPORT_STAT_FILE) { 199 | int ret = pyexec_file(main_py); 200 | if (!ret) { 201 | printf("%s: execution error\n\r", main_py); 202 | } 203 | } 204 | } 205 | } 206 | #endif 207 | 208 | #ifdef MICROPY_HW_USBHOST 209 | // USB host library initialization must be called after MicroPython's 210 | // initialization because USB host library allocates its memory blocks 211 | // using MemoryAllocate in usbhost.c which in turn calls m_alloc(). 212 | if (!use_qemu) { 213 | rpi_usb_host_init(); 214 | usbkbd_setup(); 215 | } 216 | #endif 217 | 218 | for (;;) { 219 | if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { 220 | if (pyexec_raw_repl() != 0) { 221 | break; 222 | } 223 | } else { 224 | if (pyexec_friendly_repl() != 0) { 225 | break; 226 | } 227 | } 228 | } 229 | #ifdef MICROPY_HW_USBHOST 230 | if (!use_qemu) { 231 | rpi_usb_host_deinit(); 232 | } 233 | #endif 234 | mp_deinit(); 235 | printf("PYB: soft reboot\n"); 236 | } 237 | return 0; 238 | } 239 | 240 | void nlr_jump_fail(void *val) { 241 | while (1); 242 | } 243 | 244 | void NORETURN __fatal_error(const char *msg) { 245 | while (1); 246 | } 247 | 248 | 249 | #ifdef NDEBUG 250 | void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { 251 | __fatal_error("Assertion failed"); 252 | } 253 | #else 254 | void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { 255 | printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); 256 | __fatal_error("Assertion failed"); 257 | } 258 | #endif 259 | 260 | -------------------------------------------------------------------------------- /raspberrypi/mini-uart.c: -------------------------------------------------------------------------------- 1 | #include "bcm283x_gpio.h" 2 | #include "bcm283x_aux.h" 3 | #include "bcm283x_it.h" 4 | #include "rpi.h" 5 | #include "mini-uart.h" 6 | #include "lib/utils/interrupt_char.h" 7 | 8 | // Set this to 0 for avoiding mini-UART interrupts. 9 | #define USE_IRQ 1 10 | 11 | mini_uart_t volatile *mini_uart = (mini_uart_t*) AUX_MU; 12 | 13 | #define RX_CH (mini_uart->IO) 14 | #define TX_FULL ((mini_uart->LSR & 0x20) == 0x0) 15 | #define TX_CH(c) (mini_uart->IO = (c)) 16 | 17 | 18 | #if USE_IRQ 19 | // Receive interrupt only. Transmit interrput is not supported. 20 | 21 | #define IRQ_MU_PENDING ((mini_uart->IIR & 1U) == 0) 22 | 23 | #define RX_BUF_SIZE 0xfff 24 | 25 | volatile unsigned char rbuf[RX_BUF_SIZE + 1]; 26 | volatile uint32_t rbuf_w; 27 | volatile uint32_t rbuf_r; 28 | 29 | #define RX_BUF_INIT {rbuf_w = 0; rbuf_r = 0;} 30 | #define RX_EMPTY (rbuf_w == rbuf_r) 31 | #define RX_FULL (((rbuf_w + 1) & RX_BUF_SIZE) == rbuf_r) 32 | 33 | #define RX_WRITE(c) \ 34 | rbuf[rbuf_w] = (c); \ 35 | rbuf_w = (rbuf_w + 1) & RX_BUF_SIZE; \ 36 | if RX_EMPTY { rbuf_r = (rbuf_r + 1) & RX_BUF_SIZE; } 37 | 38 | #define RX_READ(c) \ 39 | c = rbuf[rbuf_r]; \ 40 | rbuf_r = (rbuf_r + 1) & RX_BUF_SIZE; 41 | 42 | static void mini_uart_irq_enable() { 43 | IRQ_ENABLE1 = IRQ_AUX; 44 | } 45 | 46 | static void mini_uart_irq_disable() { 47 | IRQ_DISABLE1 = IRQ_AUX; 48 | } 49 | 50 | void isr_irq_mini_uart(void) { 51 | while (IRQ_MU_PENDING) { 52 | if (mini_uart->IIR & MU_IIR_RX_AVAIL) { 53 | unsigned char c = (RX_CH & 0xff); 54 | if (c == mp_interrupt_char) { 55 | mp_keyboard_interrupt(); 56 | } else { 57 | RX_WRITE(c); 58 | } 59 | } 60 | } 61 | } 62 | 63 | #else // USE_IRQ 64 | 65 | #define RX_EMPTY !(mini_uart->LSR & 1U) 66 | #define RX_READ(c) (c = RX_CH) 67 | 68 | void isr_irq_mini_uart(void) { 69 | return; 70 | } 71 | 72 | #endif // USE_IRQ 73 | 74 | void mini_uart_set_speed(uint32_t speed) { 75 | mini_uart->CNTL = 0; // disable mini uart 76 | mini_uart->BAUD = ((rpi_freq_core() / speed) >> 3) - 1; 77 | mini_uart->CNTL = 3; // enable mini uart 78 | } 79 | 80 | void mini_uart_init() { 81 | // set GPIO14, GPIO15, alternate function 5 82 | IOREG(GPFSEL1) = (GPF_ALT_5 << (3*4)) | (GPF_ALT_5 << (3*5)); 83 | 84 | // UART basic settings 85 | #if USE_IRQ 86 | mini_uart_irq_disable(); 87 | #endif 88 | 89 | AUX_ENABLES |= AUX_FLAG_MU; 90 | mini_uart->IER = 0; // disable interrupts 91 | mini_uart->CNTL = 0; // disable mini uart 92 | 93 | #if USE_IRQ 94 | mini_uart->IER = MU_IER_RX_AVAIL; // enable receive interrupt 95 | #else 96 | mini_uart->IER = 0; // disable receive/transmit interrupts 97 | #endif 98 | 99 | mini_uart->IIR = 0xC6; // enable FIFO(0xC0), clear FIFO(0x06) 100 | mini_uart->MCR = 0; // set RTS to High 101 | 102 | // data and speed (mini uart is always parity none, 1 start bit 1 stop bit) 103 | mini_uart->LCR = 3; // 8 bits; Note: BCM2835 manual p14 is incorrect 104 | mini_uart->BAUD = ((rpi_freq_core() / 115200) >> 3) - 1; 105 | // mini_uart->BAUD = 270; // 1115200 bps @ core_freq=250 106 | // mini_uart->BAUD = 434; // 1115200 bps @ core_freq=400 107 | 108 | // enable transmit and receive 109 | #if USE_IRQ 110 | RX_BUF_INIT; 111 | mini_uart_irq_enable(); 112 | #endif 113 | 114 | mini_uart->CNTL = 3; 115 | }; 116 | 117 | void mini_uart_putc(char c) { 118 | while(TX_FULL) { 119 | } 120 | TX_CH(c); 121 | } 122 | 123 | uint32_t mini_uart_getc(void) { 124 | uint32_t c; 125 | 126 | while(RX_EMPTY) { 127 | } 128 | RX_READ(c); 129 | return c & 0xffU; 130 | } 131 | 132 | uint32_t mini_uart_rx_state(void) { 133 | return !RX_EMPTY; 134 | } 135 | -------------------------------------------------------------------------------- /raspberrypi/mini-uart.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_MINI_UART_H 2 | #define MICROPY_INCLUDED_RPI_MINI_UART_H 3 | 4 | #include 5 | 6 | void mini_uart_init(); 7 | void mini_uart_putc(char c); 8 | uint32_t mini_uart_getc(void); 9 | uint32_t mini_uart_rx_state(void); 10 | void mini_uart_set_speed(uint32_t speed); 11 | 12 | void isr_irq_mini_uart(void); 13 | 14 | #endif // MICROPY_INCLUDED_RPI_MINI_UART_H 15 | -------------------------------------------------------------------------------- /raspberrypi/modgpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/runtime.h" 5 | #include "py/mphal.h" 6 | #include "py/obj.h" 7 | 8 | #include "gpu.h" 9 | #include "gpu_vc_property.h" 10 | 11 | static fb_info_t fb_info = {1920, 1080, 480, 270, 0, 16, 0, 0, 0, 0}; 12 | 13 | /// \method fb_init(w=640, h=480, bpp=16, screen_w=0, screen_h=0, offset_x=0, offset_y=0) 14 | /// This initialises frame buffer resolution, bpp, video signal settings. 15 | /// When called, GPU allocates framebuffer memory. 16 | /// Parameters: 17 | /// - w, h, bpp : actual frame buffer size and bpp 18 | /// - screen_w, screen_h : display resolution ; 0 means value is same as w,h 19 | /// - offset_x, offset_y : framebuffer position from screen's top left corner 20 | /// Static variable fb_info holds framebuffer settings. 21 | /// - w, h, bpp, screen_w, screen_h, offset_x, offset_y: passed as parameter 22 | /// - rowbytes : number of bytes in a row 23 | /// - buf_addr : pointer to the frame buffer allocated by GPU 24 | /// - buf_size : number of bytes of the frame buffer 25 | STATIC mp_obj_t gpu_fb_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 26 | static const mp_arg_t allowed_args[] = { 27 | { MP_QSTR_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 640} }, 28 | { MP_QSTR_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 480} }, 29 | { MP_QSTR_bpp, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} }, 30 | { MP_QSTR_screen_w, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 31 | { MP_QSTR_screen_h, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 32 | { MP_QSTR_offset_x, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 33 | { MP_QSTR_offset_y, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 34 | }; 35 | 36 | // parse args 37 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 38 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 39 | 40 | // set the GPU configuration values 41 | fb_info.w = args[0].u_int; 42 | fb_info.h = args[1].u_int; 43 | fb_info.bpp = args[2].u_int; 44 | fb_info.screen_w = args[3].u_int != 0 ? args[3].u_int : args[0].u_int; 45 | fb_info.screen_h = args[4].u_int != 0 ? args[4].u_int : args[1].u_int; 46 | fb_info.offset_x = args[5].u_int; 47 | fb_info.offset_y = args[6].u_int; 48 | 49 | // init the video core 50 | rpi_fb_init(&fb_info); 51 | 52 | return mp_const_none; 53 | } 54 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(gpu_fb_init_obj, 2, gpu_fb_init); 55 | 56 | /// \function gpu.fb_data() 57 | /// This returns the pointer to frame buffer as byte array if it is allocated. 58 | STATIC mp_obj_t gpu_fb_data(void) { 59 | if (fb_info.buf_addr == 0) { 60 | return mp_const_none; 61 | } else { 62 | return mp_obj_new_bytearray_by_ref(fb_info.buf_size, (void *) PHYSICALADDR(fb_info.buf_addr)); 63 | } 64 | } 65 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(gpu_fb_data_obj, gpu_fb_data); 66 | 67 | /// \function gpu.fb_rowbytes() 68 | /// This returns the number of bytes in a row of the frame buffer. 69 | STATIC mp_obj_t gpu_fb_rowbytes(void) { 70 | if (fb_info.rowbytes == 0) { 71 | return mp_const_none; 72 | } else { 73 | return mp_obj_new_int(fb_info.rowbytes); 74 | } 75 | } 76 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(gpu_fb_rowbytes_obj, gpu_fb_rowbytes); 77 | 78 | 79 | 80 | STATIC const mp_rom_map_elem_t gpu_module_globals_table[] = { 81 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gpu) }, 82 | 83 | { MP_ROM_QSTR(MP_QSTR_fb_init), MP_ROM_PTR(&gpu_fb_init_obj) }, 84 | { MP_ROM_QSTR(MP_QSTR_fb_data), MP_ROM_PTR(&gpu_fb_data_obj) }, 85 | { MP_ROM_QSTR(MP_QSTR_fb_rowbytes), MP_ROM_PTR(&gpu_fb_rowbytes_obj) }, 86 | { MP_ROM_QSTR(MP_QSTR_vc_property), MP_ROM_PTR(&gpu_vc_property_obj) }, 87 | }; 88 | 89 | STATIC MP_DEFINE_CONST_DICT(gpu_module_globals, gpu_module_globals_table); 90 | 91 | const mp_obj_module_t gpu_module = { 92 | .base = { &mp_type_module }, 93 | .globals = (mp_obj_dict_t*) &gpu_module_globals, 94 | }; 95 | -------------------------------------------------------------------------------- /raspberrypi/modmachine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/obj.h" 5 | #include "py/runtime.h" 6 | #include "py/mphal.h" 7 | #include "modmachine.h" 8 | #include "arm_exceptions.h" 9 | #include "machine_usb_mode.h" 10 | 11 | STATIC mp_obj_t machine_disable_irq(void) { 12 | arm_irq_disable(); 13 | return mp_const_none; 14 | } 15 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); 16 | 17 | STATIC mp_obj_t machine_enable_irq(void) { 18 | arm_irq_enable(); 19 | return mp_const_none; 20 | } 21 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_enable_irq_obj, machine_enable_irq); 22 | 23 | STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { 24 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, 25 | { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, 26 | { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, 27 | { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&machine_sdcard_type) }, 28 | { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, 29 | { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, 30 | { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, 31 | { MP_ROM_QSTR(MP_QSTR_Clock), MP_ROM_PTR(&machine_clock_type) }, 32 | 33 | { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, 34 | { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, 35 | #ifdef MICROPY_HW_USBHOST 36 | { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&machine_usb_mode_obj) }, 37 | #endif 38 | }; 39 | STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); 40 | 41 | const mp_obj_module_t mp_module_machine = { 42 | .base = { &mp_type_module }, 43 | .globals = (mp_obj_dict_t*) &machine_module_globals, 44 | }; 45 | -------------------------------------------------------------------------------- /raspberrypi/modmachine.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_MODMACHINE_H 2 | #define MICROPY_INCLUDED_RPI_MODMACHINE_H 3 | 4 | extern const mp_obj_type_t machine_pin_type; 5 | extern const mp_obj_type_t machine_timer_type; 6 | extern const mp_obj_type_t machine_sdcard_type; 7 | extern const mp_obj_type_t machine_i2c_type; 8 | extern const mp_obj_type_t machine_spi_type; 9 | extern const mp_obj_type_t machine_pwm_type; 10 | extern const mp_obj_type_t machine_clock_type; 11 | 12 | #endif // MICROPY_INCLUDED_RPI_MODMACHINE_H 13 | -------------------------------------------------------------------------------- /raspberrypi/modmcu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "py/obj.h" 5 | #include "py/objint.h" 6 | #include "extmod/machine_mem.h" 7 | #include "bcm283x.h" 8 | 9 | STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { 10 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mcu) }, 11 | 12 | { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, 13 | { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, 14 | { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, 15 | { MP_ROM_QSTR(MP_QSTR_IO_BASE), MP_ROM_INT(IO_BASE) }, 16 | }; 17 | 18 | STATIC MP_DEFINE_CONST_DICT(mcu_module_globals, mcu_module_globals_table); 19 | 20 | const mp_obj_module_t mcu_module = { 21 | .base = { &mp_type_module }, 22 | .globals = (mp_obj_dict_t*) &mcu_module_globals, 23 | }; 24 | -------------------------------------------------------------------------------- /raspberrypi/moduos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "extmod/vfs.h" 28 | #include "extmod/vfs_fat.h" 29 | #include "extmod/misc.h" 30 | 31 | STATIC const mp_rom_map_elem_t os_module_globals_table[] = { 32 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, 33 | 34 | // MicroPython extensions 35 | #if MICROPY_VFS_FAT 36 | { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, 37 | { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, 38 | { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, 39 | { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, 40 | { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, 41 | { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, 42 | { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, 43 | { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, 44 | { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, 45 | { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, 46 | { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, 47 | { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, 48 | { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, 49 | #endif 50 | #if MICROPY_PY_OS_DUPTERM 51 | { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, 52 | #endif 53 | }; 54 | 55 | STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); 56 | 57 | const mp_obj_module_t mp_module_uos = { 58 | .base = { &mp_type_module }, 59 | .globals = (mp_obj_dict_t*)&os_module_globals, 60 | }; 61 | -------------------------------------------------------------------------------- /raspberrypi/modutime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "py/runtime.h" 31 | #include "py/smallint.h" 32 | #include "py/obj.h" 33 | #include "lib/timeutils/timeutils.h" 34 | #include "extmod/utime_mphal.h" 35 | #include "rpi.h" 36 | 37 | /// \module time - time related functions 38 | /// 39 | /// The `time` module provides functions for getting the current time and date, 40 | /// and for sleeping. 41 | 42 | /// \function localtime([secs]) 43 | /// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which 44 | /// contains: (year, month, mday, hour, minute, second, weekday, yearday) 45 | /// If secs is not provided or None, then the current time from the RTC is used. 46 | /// year includes the century (for example 2014) 47 | /// month is 1-12 48 | /// mday is 1-31 49 | /// hour is 0-23 50 | /// minute is 0-59 51 | /// second is 0-59 52 | /// weekday is 0-6 for Mon-Sun. 53 | /// yearday is 1-366 54 | STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { 55 | timeutils_struct_time_t tm; 56 | mp_int_t seconds; 57 | 58 | if (n_args == 0 || args[0] == mp_const_none) { 59 | // uses the number of seconds after power on because RPi has no RTC 60 | seconds = systime() / 1000000; 61 | } else { 62 | seconds = mp_obj_get_int(args[0]); 63 | } 64 | timeutils_seconds_since_2000_to_struct_time(seconds, &tm); 65 | mp_obj_t tuple[8] = { 66 | mp_obj_new_int(tm.tm_year), 67 | mp_obj_new_int(tm.tm_mon), 68 | mp_obj_new_int(tm.tm_mday), 69 | mp_obj_new_int(tm.tm_hour), 70 | mp_obj_new_int(tm.tm_min), 71 | mp_obj_new_int(tm.tm_sec), 72 | mp_obj_new_int(tm.tm_wday), 73 | mp_obj_new_int(tm.tm_yday), 74 | }; 75 | return mp_obj_new_tuple(8, tuple); 76 | } 77 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); 78 | 79 | 80 | /// \function mktime() 81 | /// This is inverse function of localtime. It's argument is a full 8-tuple 82 | /// which expresses a time as per localtime. It returns an integer which is 83 | /// the number of seconds since Jan 1, 2000. 84 | STATIC mp_obj_t time_mktime(mp_obj_t tuple) { 85 | 86 | size_t len; 87 | mp_obj_t *elem; 88 | 89 | mp_obj_get_array(tuple, &len, &elem); 90 | 91 | // localtime generates a tuple of len 8. CPython uses 9, so we accept both. 92 | if (len < 8 || len > 9) { 93 | nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len)); 94 | } 95 | 96 | return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), 97 | mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), 98 | mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); 99 | } 100 | MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); 101 | 102 | /// \function time() 103 | /// Returns the number of seconds, as an integer, since 1/1/2000. 104 | STATIC mp_obj_t time_time(void) { 105 | // returns the number of seconds after power on because RPi has no RTC 106 | return mp_obj_new_int(systime() / 1000000); 107 | } 108 | MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); 109 | 110 | STATIC const mp_rom_map_elem_t time_module_globals_table[] = { 111 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, 112 | 113 | { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, 114 | { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, 115 | { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, 116 | { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, 117 | { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, 118 | { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, 119 | { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, 120 | { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, 121 | { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, 122 | { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, 123 | { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, 124 | }; 125 | 126 | STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); 127 | 128 | const mp_obj_module_t utime_module = { 129 | .base = { &mp_type_module }, 130 | .globals = (mp_obj_dict_t*)&time_module_globals, 131 | }; 132 | -------------------------------------------------------------------------------- /raspberrypi/mpconfigport.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "arm_exceptions.h" 3 | #include "usbhost.h" 4 | 5 | // options to control how MicroPython is built 6 | #define MICROPY_DEBUG_VERBOSE (0) 7 | #define MICROPY_QSTR_BYTES_IN_HASH (1) 8 | #define MICROPY_ALLOC_PATH_MAX (512) 9 | #define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) 10 | #define MICROPY_EMIT_X64 (0) 11 | #define MICROPY_EMIT_X86 (0) 12 | #define MICROPY_EMIT_THUMB (0) 13 | #define MICROPY_EMIT_ARM (0) 14 | #define MICROPY_EMIT_XTENSA (0) 15 | #define MICROPY_EMIT_INLINE_THUMB (0) 16 | #define MICROPY_EMIT_INLINE_THUMB_ARMV7M (0) 17 | #define MICROPY_EMIT_INLINE_THUMB_FLOAT (0) 18 | #define MICROPY_COMP_MODULE_CONST (1) 19 | #define MICROPY_COMP_CONST (1) 20 | #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) 21 | #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) 22 | #define MICROPY_STACK_CHECK (1) 23 | #define MICROPY_MEM_STATS (0) 24 | #define MICROPY_DEBUG_PRINTERS (0) 25 | #define MICROPY_READER_VFS (MICROPY_VFS) 26 | #define MICROPY_ENABLE_GC (1) 27 | #define MICROPY_ENABLE_FINALISER (1) 28 | #define MICROPY_HELPER_REPL (1) 29 | #define MICROPY_REPL_EMACS_KEYS (1) 30 | #define MICROPY_REPL_AUTO_INDENT (1) 31 | #define MICROPY_ENABLE_SOURCE_LINE (1) 32 | #define MICROPY_ENABLE_DOC_STRING (1) 33 | #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) 34 | #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) 35 | #define MICROPY_PY_ASYNC_AWAIT (1) 36 | #define MICROPY_USE_INTERNAL_ERRNO (1) 37 | #define MICROPY_PY_DESCRIPTORS (1) 38 | #define MICROPY_PY_ALL_SPECIAL_METHODS (1) 39 | #define MICROPY_PY_BUILTINS_STR_UNICODE (1) 40 | #define MICROPY_PY_BUILTINS_BYTEARRAY (1) 41 | #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) 42 | #define MICROPY_PY_BUILTINS_ENUMERATE (1) 43 | #define MICROPY_PY_BUILTINS_FROZENSET (1) 44 | #define MICROPY_PY_BUILTINS_REVERSED (1) 45 | #define MICROPY_PY_BUILTINS_SET (1) 46 | #define MICROPY_PY_BUILTINS_SLICE (1) 47 | #define MICROPY_PY_BUILTINS_PROPERTY (1) 48 | #define MICROPY_PY_BUILTINS_HELP (1) 49 | //#define MICROPY_PY_BUILTINS_HELP_TEXT rpi_help_text 50 | #define MICROPY_PY_BUILTINS_HELP_MODULES (1) 51 | #define MICROPY_PY___FILE__ (1) 52 | #define MICROPY_PY_GC (1) 53 | #define MICROPY_PY_ARRAY (1) 54 | #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) 55 | #define MICROPY_PY_ATTRTUPLE (1) 56 | #define MICROPY_PY_COLLECTIONS (1) 57 | #define MICROPY_PY_COLLECTIONS_DEQUE (1) 58 | #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) 59 | #define MICROPY_PY_CMATH (1) 60 | #define MICROPY_PY_IO (1) 61 | #define MICROPY_PY_IO_IOBASE (1) 62 | #define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT) // because mp_type_fileio/textio point to fatfs impl 63 | #define MICROPY_PY_STRUCT (1) 64 | #define MICROPY_PY_SYS (1) 65 | #define MICROPY_PY_SYS_MAXSIZE (1) 66 | #define MICROPY_PY_SYS_EXIT (1) 67 | #define MICROPY_PY_SYS_STDFILES (1) 68 | #define MICROPY_PY_SYS_STDIO_BUFFER (1) 69 | #define MICROPY_PY_UERRNO (1) 70 | #define MICROPY_PY_UBINASCII (1) 71 | #define MICROPY_PY_UCTYPES (1) 72 | #define MICROPY_PY_UHASHLIB (1) 73 | #define MICROPY_PY_UHEAPQ (1) 74 | #define MICROPY_PY_UTIMEQ (1) 75 | #define MICROPY_PY_UJSON (1) 76 | #define MICROPY_PY_URANDOM (1) 77 | #define MICROPY_PY_URE (1) 78 | #define MICROPY_PY_URE_SUB (1) 79 | #define MICROPY_PY_SYS_EXC_INFO (1) 80 | #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) 81 | #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) 82 | #define MICROPY_PY_MACHINE (1) 83 | #define MICROPY_PY_UTIME_MP_HAL (1) 84 | #define MICROPY_PY_UZLIB (1) 85 | #define MICROPY_PY_FRAMEBUF (1) 86 | #define MICROPY_PY_VFS (1) 87 | #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) 88 | #define MICROPY_PY_OS_DUPTERM (1) 89 | #define MICROPY_CPYTHON_COMPAT (1) 90 | #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) 91 | #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) 92 | #define MICROPY_MODULE_WEAK_LINKS (1) 93 | #define MICROPY_USE_INTERNAL_PRINTF (1) 94 | #define MICROPY_ENABLE_SCHEDULER (1) 95 | #define MICROPY_SCHEDULER_DEPTH (8) 96 | #define MICROPY_STREAMS_NON_BLOCK (1) 97 | 98 | #define MICROPY_KBD_EXCEPTION (1) 99 | 100 | #define MICROPY_VFS (1) 101 | #define MICROPY_FATFS_ENABLE_LFN (1) 102 | #define MICROPY_FATFS_RPATH (2) 103 | #define MICROPY_FATFS_MAX_SS (4096) 104 | #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ 105 | #define MICROPY_VFS_FAT (1) 106 | #define MICROPY_FATFS_MULTI_PARTITION (1) 107 | 108 | // type definitions for the specific machine 109 | 110 | #define malloc(n) m_malloc(n) 111 | #define free(p) m_free(p) 112 | #define realloc(p, n) m_realloc(p, n) 113 | 114 | #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) 115 | 116 | #define MP_SSIZE_MAX (0x7fffffff) 117 | 118 | #define UINT_FMT "%u" 119 | #define INT_FMT "%d" 120 | 121 | typedef int mp_int_t; // must be pointer size 122 | typedef unsigned mp_uint_t; // must be pointer size 123 | typedef long mp_off_t; 124 | 125 | // dummy print 126 | #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) 127 | 128 | extern const struct _mp_obj_module_t mcu_module; 129 | extern const struct _mp_obj_module_t utime_module; 130 | extern const struct _mp_obj_module_t gpu_module; 131 | extern const struct _mp_obj_module_t mp_module_uos; 132 | 133 | #define mp_type_fileio mp_type_vfs_fat_fileio 134 | #define mp_type_textio mp_type_vfs_fat_textio 135 | 136 | // use vfs's functions for import stat and builtin open 137 | #define mp_import_stat mp_vfs_import_stat 138 | #define mp_builtin_open mp_vfs_open 139 | #define mp_builtin_open_obj mp_vfs_open_obj 140 | 141 | // extra built in names to add to the global namespace 142 | #define MICROPY_PORT_BUILTINS \ 143 | { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, 144 | 145 | #define MICROPY_PORT_BUILTIN_MODULES \ 146 | { MP_ROM_QSTR(MP_QSTR_mcu), MP_ROM_PTR(&mcu_module) }, \ 147 | { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&utime_module) }, \ 148 | { MP_ROM_QSTR(MP_QSTR_gpu), MP_ROM_PTR(&gpu_module) }, \ 149 | { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ 150 | { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ 151 | 152 | #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ 153 | { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ 154 | { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) }, \ 155 | { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ 156 | { MP_ROM_QSTR(MP_QSTR_hashlib), MP_ROM_PTR(&mp_module_uhashlib) }, \ 157 | { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) }, \ 158 | { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ 159 | { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ 160 | { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mp_module_urandom) }, \ 161 | { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_ure) }, \ 162 | { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ 163 | { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&utime_module) }, \ 164 | { MP_ROM_QSTR(MP_QSTR_zlib), MP_ROM_PTR(&mp_module_uzlib) }, \ 165 | 166 | // Raspberry Pi CPU(ARMv6) can enable/disable all irqs by setting 167 | // bit 7 of CPSR so we do not need to save/restore irq flags state. 168 | 169 | __attribute__(( always_inline )) static inline void enable_irq(mp_uint_t state) { 170 | arm_irq_enable(); 171 | } 172 | 173 | __attribute__(( always_inline )) static inline mp_uint_t disable_irq(void) { 174 | arm_irq_disable(); 175 | return 0x80; 176 | } 177 | 178 | //#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() 179 | //#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) 180 | 181 | // We need to provide a declaration/definition of alloca() 182 | #include 183 | 184 | #ifdef RPI1 185 | #define MICROPY_HW_BOARD_NAME "Raspberry Pi" 186 | #define MICROPY_HW_MCU_NAME "ARM1176JZF-S" 187 | #else 188 | #define MICROPY_HW_BOARD_NAME "Raspberry Pi2" 189 | #define MICROPY_HW_MCU_NAME "Cortex-A7" 190 | #endif 191 | 192 | #define MICROPY_PY_SYS_PLATFORM "raspberrypi" 193 | 194 | #define MP_STATE_PORT MP_STATE_VM 195 | 196 | #define MICROPY_PORT_ROOT_POINTERS \ 197 | const char *readline_hist[8]; \ 198 | hcd_globals_t *hcd_globals; \ 199 | 200 | -------------------------------------------------------------------------------- /raspberrypi/mpconfigport.mk: -------------------------------------------------------------------------------- 1 | MICROPY_HW_USBHOST ?=0 2 | MICROPY_MOUNT_SD_CARD ?=1 3 | -------------------------------------------------------------------------------- /raspberrypi/mphalport.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include "py/mpconfig.h" 5 | #include "py/obj.h" 6 | #include "rpi.h" 7 | #include "mphalport.h" 8 | #include "mini-uart.h" 9 | #include "uart.h" 10 | #include "extmod/misc.h" 11 | 12 | #ifdef MICROPY_HW_USBHOST 13 | #include "usbkbd.h" 14 | #endif 15 | 16 | // Time and delay 17 | 18 | void mp_hal_delay_ms(mp_uint_t ms) { 19 | uint64_t end_time; 20 | 21 | end_time = systime() + ms * 1000; 22 | while(systime() < end_time) { 23 | extern void mp_handle_pending(void); 24 | mp_handle_pending(); 25 | } 26 | 27 | return; 28 | } 29 | 30 | void mp_hal_delay_us(mp_uint_t us) { 31 | uint64_t end_time; 32 | 33 | end_time = systime() + us; 34 | while(systime() < end_time); 35 | 36 | return; 37 | } 38 | 39 | mp_uint_t mp_hal_ticks_cpu(void) { 40 | return systime(); 41 | } 42 | 43 | mp_uint_t mp_hal_ticks_us(void) { 44 | return systime(); 45 | } 46 | 47 | mp_uint_t mp_hal_ticks_ms(void) { 48 | return systime() / 1000; 49 | } 50 | 51 | 52 | // standard I/O for REPL 53 | 54 | static void (*_uart_putc)(char c); 55 | static uint32_t (*_uart_getc)(void); 56 | static uint32_t (*_uart_rx_state)(void); 57 | 58 | void uart_init(std_io_t interface) { 59 | switch(interface) { 60 | case UART_QEMU: 61 | uart0_qemu_init(); 62 | _uart_putc = &uart0_putc; 63 | _uart_getc = &uart0_getc; 64 | _uart_rx_state = &uart0_rx_state; 65 | break; 66 | default: 67 | mini_uart_init(); 68 | _uart_putc = &mini_uart_putc; 69 | _uart_getc = &mini_uart_getc; 70 | _uart_rx_state = &mini_uart_rx_state; 71 | break; 72 | } 73 | } 74 | 75 | void uart_putc(char c) { 76 | _uart_putc(c); 77 | } 78 | 79 | uint32_t uart_getc(void) { 80 | return _uart_getc(); 81 | } 82 | 83 | void uart_write (const char* str, uint32_t len) { 84 | for (uint32_t i = 0; i < len; i++ ) { 85 | uart_putc(*str++); 86 | } 87 | } 88 | 89 | uint32_t uart_rx_state(void) { 90 | return _uart_rx_state(); 91 | } 92 | 93 | #ifdef MICROPY_HW_USBHOST 94 | static usbkbd_t usbkbd; 95 | 96 | void usbkbd_setup() { 97 | usbkbd_init(&usbkbd); 98 | } 99 | 100 | #endif 101 | // Receive single character 102 | int mp_hal_stdin_rx_chr(void) { 103 | for(;;) { 104 | #ifdef MICROPY_HW_USBHOST 105 | int result; 106 | if ((result = usbkbd_getc(&usbkbd)) >= 0) { 107 | return result; 108 | } 109 | #endif 110 | if (uart_rx_state()) { 111 | return uart_getc(); 112 | } 113 | extern void mp_handle_pending(void); 114 | mp_handle_pending(); 115 | } 116 | } 117 | 118 | // Send string of given length 119 | void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { 120 | uart_write(str,len); 121 | #ifdef MICROPY_PY_OS_DUPTERM 122 | mp_uos_dupterm_tx_strn(str, len); 123 | #endif 124 | } 125 | -------------------------------------------------------------------------------- /raspberrypi/mphalport.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "py/obj.h" 3 | 4 | void mp_hal_delay_ms(mp_uint_t ms); 5 | void mp_hal_delay_us(mp_uint_t us); 6 | mp_uint_t mp_hal_ticks_cpu(void); 7 | mp_uint_t mp_hal_ticks_us(void); 8 | mp_uint_t mp_hal_ticks_ms(void); 9 | 10 | void mp_hal_set_interrupt_char(int c); 11 | int mp_hal_stdin_rx_chr(void); 12 | void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len); 13 | 14 | typedef enum std_io_t { 15 | MINI_UART = 0, 16 | UART, 17 | UART_QEMU 18 | } std_io_t; 19 | 20 | void uart_init(std_io_t interface); 21 | 22 | #ifdef MICROPY_HW_USBHOST 23 | #include "usbkbd.h" 24 | 25 | void usbkbd_setup(); 26 | #endif 27 | -------------------------------------------------------------------------------- /raspberrypi/pwm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "bcm283x_pwm.h" 5 | #include "pwm.h" 6 | 7 | void pwm_set_ctl(uint32_t id, uint32_t flags) { 8 | if (id < 2) { 9 | uint32_t mask = ~(0xff << id * 8); 10 | pwm_t *pwm = (pwm_t *)(PWM); 11 | pwm->CTL = (pwm->CTL & mask) | flags << id * 8; 12 | } 13 | } 14 | 15 | uint32_t pwm_get_ctl(uint32_t id) { 16 | pwm_t *pwm = (pwm_t *)(PWM); 17 | if (id == 0) { 18 | return pwm->CTL & 0xff; 19 | } else { 20 | return (pwm->CTL >> 8) & 0xff; 21 | } 22 | } 23 | 24 | bool pwm_is_active(uint32_t id) { 25 | pwm_t *pwm = (pwm_t *)(PWM); 26 | if (id == 0) { 27 | return ((pwm->CTL & CTL_PWEN1) > 0); 28 | } else if (id == 1) { 29 | return ((pwm->CTL & CTL_PWEN2) > 0); 30 | } 31 | return false; 32 | } 33 | 34 | void pwm_set_active(uint32_t id, bool active) { 35 | if (id < 2) { 36 | pwm_t *pwm = (pwm_t *)(PWM); 37 | if (active) { 38 | pwm->CTL = pwm->CTL | CTL_PWEN1 << id * 8; 39 | } else { 40 | uint32_t mask = ~(CTL_PWEN1 << id * 8); 41 | pwm->CTL = pwm->CTL & mask; 42 | } 43 | } 44 | } 45 | 46 | void pwm_fifo_set_active(bool active) { 47 | pwm_t *pwm = (pwm_t *)(PWM); 48 | if (active) { 49 | pwm->CTL |= CTL_PWEN1 | CTL_PWEN2; 50 | } else { 51 | uint32_t mask = ~(CTL_PWEN1 | CTL_PWEN2); 52 | pwm->CTL &= mask; 53 | } 54 | } 55 | 56 | uint32_t pwm_get_period(uint32_t id) { 57 | pwm_t *pwm = (pwm_t *)(PWM); 58 | if (id == 0) { 59 | return pwm->RNG1; 60 | } else { 61 | return pwm->RNG2; 62 | } 63 | } 64 | 65 | uint32_t pwm_get_duty_ticks(uint32_t id) { 66 | pwm_t *pwm = (pwm_t *)(PWM); 67 | if (id == 0) { 68 | return pwm->DAT1; 69 | } else { 70 | return pwm->DAT2; 71 | } 72 | } 73 | 74 | void pwm_set_period(uint32_t id, uint32_t period) { 75 | pwm_t *pwm = (pwm_t *)(PWM); 76 | if (id == 0) { 77 | pwm->RNG1 = period; 78 | } else { 79 | pwm->RNG2 = period; 80 | } 81 | } 82 | 83 | void pwm_set_duty_ticks(uint32_t id, uint32_t duty_ticks) { 84 | pwm_t *pwm = (pwm_t *)(PWM); 85 | if (id == 0) { 86 | pwm->DAT1 = duty_ticks; 87 | } else { 88 | pwm->DAT2 = duty_ticks; 89 | } 90 | } 91 | 92 | bool pwm_fifo_available() { 93 | pwm_t *pwm = (pwm_t *)(PWM); 94 | return ((pwm->STA & STA_FULL1) == 0); 95 | } 96 | 97 | bool pwm_fifo_queue(uint32_t data) { 98 | pwm_t *pwm = (pwm_t *)(PWM); 99 | if (pwm->STA & STA_FULL1) { 100 | return false; 101 | } else { 102 | pwm->FIF1 = data; 103 | if (pwm->STA & STA_WERR1) { 104 | pwm->STA |= STA_WERR1; 105 | } 106 | return true; 107 | } 108 | } 109 | 110 | void pwm_fifo_clear() { 111 | pwm_t *pwm = (pwm_t *)(PWM); 112 | pwm_set_ctl(0, pwm->CTL | CTL_CLRF1); 113 | } 114 | 115 | void pwm_err_clear() { 116 | pwm_t *pwm = (pwm_t *)(PWM); 117 | while (pwm->STA & STA_WERR1) { 118 | pwm->STA |= STA_WERR1; 119 | } 120 | while (pwm->STA & STA_RERR1) { 121 | pwm->STA |= STA_RERR1; 122 | } 123 | while (pwm->STA & STA_GAPO1) { 124 | pwm->STA |= STA_GAPO1; 125 | } 126 | while (pwm->STA & STA_GAPO2) { 127 | pwm->STA |= STA_GAPO2; 128 | } 129 | while (pwm->STA & STA_BERR) { 130 | pwm->STA |= STA_BERR; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /raspberrypi/pwm.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_PWM_H 2 | #define MICROPY_INCLUDED_RPI_PWM_H 3 | 4 | #include 5 | #include 6 | 7 | void pwm_set_ctl(uint32_t id, uint32_t flags); 8 | uint32_t pwm_get_ctl(uint32_t id); 9 | 10 | void pwm_set_active(uint32_t id, bool active); 11 | bool pwm_is_active(uint32_t id); 12 | 13 | void pwm_set_period(uint32_t id, uint32_t period); 14 | uint32_t pwm_get_period(uint32_t id); 15 | 16 | void pwm_set_duty_ticks(uint32_t id, uint32_t duty_ticks); 17 | uint32_t pwm_get_duty_ticks(uint32_t id); 18 | 19 | bool pwm_fifo_available(); 20 | bool pwm_fifo_queue(uint32_t data); 21 | void pwm_fifo_clear(); 22 | void pwm_fifo_set_active(bool active); 23 | void pwm_err_clear(); 24 | 25 | #endif // MICROPY_INCLUDED_RPI_PWM_H 26 | -------------------------------------------------------------------------------- /raspberrypi/qstrdefsport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | // qstrs specific to this port, only needed if they aren't auto-generated 28 | 29 | // Entries for sys.path 30 | Q(/sd) 31 | Q(/sd/lib) 32 | -------------------------------------------------------------------------------- /raspberrypi/rpi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "arm_exceptions.h" 6 | #include "bcm283x.h" 7 | #include "bcm283x_it.h" 8 | #include "bcm283x_gpio.h" 9 | #include "bcm283x_aux.h" 10 | #include "bcm283x_mailbox.h" 11 | #include "bcm283x_clockmgr.h" 12 | #include "vc_property.h" 13 | #include "rpi.h" 14 | 15 | static uint32_t freq_cpu = 700000000; 16 | static uint32_t freq_core = 250000000; 17 | 18 | // System Timers 19 | 20 | systimer_t *systimer = (systimer_t *) SYSTIMER; 21 | 22 | volatile uint64_t systime(void) { 23 | uint64_t t; 24 | uint32_t chi; 25 | uint32_t clo; 26 | 27 | chi = systimer->CHI; 28 | clo = systimer->CLO; 29 | if (chi != systimer->CHI) { 30 | chi = systimer->CHI; 31 | clo = systimer->CLO; 32 | } 33 | t = chi; 34 | t = t << 32; 35 | t += clo; 36 | return t; 37 | } 38 | 39 | volatile uint64_t elapsed_from(uint64_t t) { 40 | uint64_t now; 41 | uint32_t chi; 42 | uint32_t clo; 43 | 44 | now = systime(); 45 | if (now > t) { 46 | return now - t; 47 | } else { 48 | return ULLONG_MAX - t + now; 49 | } 50 | 51 | chi = systimer->CHI; 52 | clo = systimer->CLO; 53 | if (chi != systimer->CHI) { 54 | chi = systimer->CHI; 55 | clo = systimer->CLO; 56 | } 57 | t = chi; 58 | t = t << 32; 59 | t += clo; 60 | return t; 61 | } 62 | 63 | // IRQ handler 64 | 65 | #define IRQ_SYSTIMERS (IRQ_SYSTIMER(0) | \ 66 | IRQ_SYSTIMER(1) | \ 67 | IRQ_SYSTIMER(2) | \ 68 | IRQ_SYSTIMER(3)) 69 | 70 | void __attribute__((interrupt("IRQ"))) irq_handler(void) { 71 | if (IRQ_PEND1 & IRQ_SYSTIMERS) { 72 | isr_irq_timer(); 73 | } 74 | if (IRQ_PEND1 & IRQ_AUX) { 75 | if (AUX_IRQ & AUX_FLAG_MU) { 76 | isr_irq_mini_uart(); 77 | } 78 | } 79 | } 80 | 81 | // Clock speed 82 | 83 | uint32_t rpi_freq_core() { 84 | return freq_core; 85 | } 86 | 87 | uint32_t rpi_freq_cpu() { 88 | return freq_cpu; 89 | } 90 | 91 | // Initialize Raspberry Pi peripherals 92 | 93 | #define MB_GET_CLK_RATE (0x00030002) 94 | #define CLKID_ARM (3) 95 | #define CLKID_CORE (4) 96 | enum MB_BUFF { BUFSIZE=0, MB_REQ_RES, \ 97 | TAG0, VALBUFSIZE0, REQ_RES0, VALUE00, VALUE01,\ 98 | TAG1, VALBUFSIZE1, REQ_RES1, VALUE10, VALUE11,\ 99 | ENDTAG }; 100 | 101 | static void get_clock_value() { 102 | __attribute__((aligned(16))) uint32_t clkinfo[ENDTAG + 1]; 103 | clkinfo[BUFSIZE] = 4 * (ENDTAG + 1); 104 | clkinfo[MB_REQ_RES] = MB_PROP_REQUEST; 105 | 106 | clkinfo[TAG0] = MB_GET_CLK_RATE; 107 | clkinfo[VALBUFSIZE0] = 8; 108 | clkinfo[REQ_RES0] = 0; 109 | clkinfo[VALUE00] = CLKID_ARM; 110 | clkinfo[VALUE01] = 0; 111 | 112 | clkinfo[TAG1] = MB_GET_CLK_RATE; 113 | clkinfo[VALBUFSIZE1] = 8; 114 | clkinfo[REQ_RES1] = 0; 115 | clkinfo[VALUE10] = CLKID_CORE; 116 | clkinfo[VALUE11] = 0; 117 | 118 | clkinfo[ENDTAG] = 0; 119 | 120 | mailbox_write(MB_CH_PROP_ARM, (uint32_t) BUSADDR(clkinfo) >> 4); 121 | mailbox_read(MB_CH_PROP_ARM); 122 | 123 | if (clkinfo[MB_REQ_RES] == MB_PROP_SUCCESS) { 124 | if (clkinfo[REQ_RES0] & MB_PROP_SUCCESS) { 125 | freq_cpu = clkinfo[VALUE01]; 126 | } 127 | if (clkinfo[REQ_RES1] & MB_PROP_SUCCESS) { 128 | freq_core = clkinfo[VALUE11]; 129 | } 130 | } 131 | } 132 | 133 | void rpi_init() { 134 | // read values of freq_cpu, freq_core 135 | get_clock_value(); 136 | // set PWM clock to 960KHz (19.2MHz / 20) as a default value 137 | clockmgr_config_ctl((clockmgr_t *) CM_PWM, CM_CTL_MASH_1STG | CM_CTL_ENAB | CM_CTL_SRC_OSC); 138 | clockmgr_config_div((clockmgr_t *) CM_PWM, 20, 0); 139 | // any additional initialization 140 | } 141 | 142 | -------------------------------------------------------------------------------- /raspberrypi/rpi.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_RPI_H 2 | #define MICROPY_INCLUDED_RPI_RPI_H 3 | 4 | #include 5 | #include "bcm283x_systimer.h" 6 | 7 | extern systimer_t *systimer; 8 | 9 | volatile uint64_t systime(void); 10 | volatile uint64_t elapsed_from(uint64_t t); 11 | 12 | extern void isr_irq_timer(void); 13 | extern void isr_irq_mini_uart(void); 14 | 15 | void rpi_init(); 16 | 17 | uint32_t rpi_freq_core(); 18 | uint32_t rpi_freq_cpu(); 19 | 20 | #endif // MICROPY_INCLUDED_RPI_RPI_H 21 | -------------------------------------------------------------------------------- /raspberrypi/sd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | #include "bcm283x_gpio.h" 28 | #include "mphalport.h" 29 | #include "bcm283x_systimer.h" 30 | #include "sd.h" 31 | 32 | #define MMIO_BASE IO_BASE 33 | #define wait_msec(n) mp_hal_delay_ms(n) 34 | 35 | #define VERBOSE 0 36 | 37 | #if VERBOSE 38 | extern void uart_putc(char c); 39 | extern uint32_t uart_getc(); 40 | extern void uart_write (const char* str, uint32_t len); 41 | 42 | #define uart_init() void(void) 43 | #define uart_send(c) {uart_putc(c); if (c == 0x0a) uart_putc(0x0d);} 44 | 45 | void uart_puts(char *s) { 46 | while(*s) { 47 | uart_putc(*s); 48 | if (*s == 0x0a) 49 | uart_putc(0x0d); 50 | s++; 51 | } 52 | } 53 | 54 | void uart_hex(uint32_t d) { 55 | static const char hex[16] = "0123456789ABCDEF"; 56 | uart_putc(hex[(d >> 28) & 0xf]); 57 | uart_putc(hex[(d >> 24) & 0xf]); 58 | uart_putc(hex[(d >> 20) & 0xf]); 59 | uart_putc(hex[(d >> 16) & 0xf]); 60 | uart_putc(hex[(d >> 12) & 0xf]); 61 | uart_putc(hex[(d >> 8) & 0xf]); 62 | uart_putc(hex[(d >> 4) & 0xf]); 63 | uart_putc(hex[d & 0xf]); 64 | } 65 | 66 | #else 67 | 68 | #define uart_init() void(void) 69 | #define uart_send(c) 70 | #define uart_puts(s) 71 | #define uart_hex(d) 72 | 73 | #endif 74 | 75 | #define EMMC_ARG2 ((volatile unsigned int*)(MMIO_BASE+0x00300000)) 76 | #define EMMC_BLKSIZECNT ((volatile unsigned int*)(MMIO_BASE+0x00300004)) 77 | #define EMMC_ARG1 ((volatile unsigned int*)(MMIO_BASE+0x00300008)) 78 | #define EMMC_CMDTM ((volatile unsigned int*)(MMIO_BASE+0x0030000C)) 79 | #define EMMC_RESP0 ((volatile unsigned int*)(MMIO_BASE+0x00300010)) 80 | #define EMMC_RESP1 ((volatile unsigned int*)(MMIO_BASE+0x00300014)) 81 | #define EMMC_RESP2 ((volatile unsigned int*)(MMIO_BASE+0x00300018)) 82 | #define EMMC_RESP3 ((volatile unsigned int*)(MMIO_BASE+0x0030001C)) 83 | #define EMMC_DATA ((volatile unsigned int*)(MMIO_BASE+0x00300020)) 84 | #define EMMC_STATUS ((volatile unsigned int*)(MMIO_BASE+0x00300024)) 85 | #define EMMC_CONTROL0 ((volatile unsigned int*)(MMIO_BASE+0x00300028)) 86 | #define EMMC_CONTROL1 ((volatile unsigned int*)(MMIO_BASE+0x0030002C)) 87 | #define EMMC_INTERRUPT ((volatile unsigned int*)(MMIO_BASE+0x00300030)) 88 | #define EMMC_INT_MASK ((volatile unsigned int*)(MMIO_BASE+0x00300034)) 89 | #define EMMC_INT_EN ((volatile unsigned int*)(MMIO_BASE+0x00300038)) 90 | #define EMMC_CONTROL2 ((volatile unsigned int*)(MMIO_BASE+0x0030003C)) 91 | #define EMMC_SLOTISR_VER ((volatile unsigned int*)(MMIO_BASE+0x003000FC)) 92 | 93 | // command flags 94 | #define CMD_NEED_APP 0x80000000 95 | #define CMD_RSPNS_48 0x00020000 96 | #define CMD_ERRORS_MASK 0xfff9c004 97 | #define CMD_RCA_MASK 0xffff0000 98 | 99 | // COMMANDs 100 | #define CMD_GO_IDLE 0x00000000 101 | #define CMD_ALL_SEND_CID 0x02010000 102 | #define CMD_SEND_REL_ADDR 0x03020000 103 | #define CMD_CARD_SELECT 0x07030000 104 | #define CMD_SEND_IF_COND 0x08020000 105 | #define CMD_STOP_TRANS 0x0C030000 106 | #define CMD_READ_SINGLE 0x11220010 107 | #define CMD_READ_MULTI 0x12220032 108 | #define CMD_SET_BLOCKCNT 0x17020000 109 | #define CMD_WRITE_SINGLE 0x18220000 110 | #define CMD_WRITE_MULTI 0x19220022 111 | #define CMD_APP_CMD 0x37000000 112 | #define CMD_SET_BUS_WIDTH (0x06020000|CMD_NEED_APP) 113 | #define CMD_SEND_OP_COND (0x29020000|CMD_NEED_APP) 114 | #define CMD_SEND_SCR (0x33220010|CMD_NEED_APP) 115 | 116 | // STATUS register settings 117 | #define SR_READ_AVAILABLE 0x00000800 118 | #define SR_DAT_INHIBIT 0x00000002 119 | #define SR_CMD_INHIBIT 0x00000001 120 | #define SR_APP_CMD 0x00000020 121 | 122 | // INTERRUPT register settings 123 | #define INT_DATA_TIMEOUT 0x00100000 124 | #define INT_CMD_TIMEOUT 0x00010000 125 | #define INT_READ_RDY 0x00000020 126 | #define INT_WRITE_RDY 0x00000010 127 | #define INT_DATA_DONE 0x00000002 128 | #define INT_CMD_DONE 0x00000001 129 | 130 | #define INT_ERROR_MASK 0x017E8000 131 | 132 | // CONTROL register settings 133 | #define C0_SPI_MODE_EN 0x00100000 134 | #define C0_HCTL_HS_EN 0x00000004 135 | #define C0_HCTL_DWITDH 0x00000002 136 | 137 | #define C1_SRST_DATA 0x04000000 138 | #define C1_SRST_CMD 0x02000000 139 | #define C1_SRST_HC 0x01000000 140 | #define C1_TOUNIT_DIS 0x000f0000 141 | #define C1_TOUNIT_MAX 0x000e0000 142 | #define C1_CLK_GENSEL 0x00000020 143 | #define C1_CLK_EN 0x00000004 144 | #define C1_CLK_STABLE 0x00000002 145 | #define C1_CLK_INTLEN 0x00000001 146 | 147 | // SLOTISR_VER values 148 | #define HOST_SPEC_NUM 0x00ff0000 149 | #define HOST_SPEC_NUM_SHIFT 16 150 | #define HOST_SPEC_V3 2 151 | #define HOST_SPEC_V2 1 152 | #define HOST_SPEC_V1 0 153 | 154 | // SCR flags 155 | #define SCR_SD_BUS_WIDTH_4 0x00000400 156 | #define SCR_SUPP_SET_BLKCNT 0x02000000 157 | // added by my driver 158 | #define SCR_SUPP_CCS 0x00000001 159 | 160 | #define ACMD41_VOLTAGE 0x00ff8000 161 | #define ACMD41_CMD_COMPLETE 0x80000000 162 | #define ACMD41_CMD_CCS 0x40000000 163 | #define ACMD41_ARG_HC 0x51ff8000 164 | 165 | unsigned int sd_scr[2], sd_ocr, sd_rca, sd_err, sd_hv; 166 | 167 | /** 168 | * Wait for data or command ready 169 | */ 170 | int sd_status(unsigned int mask) 171 | { 172 | int cnt = 500000; while((*EMMC_STATUS & mask) && !(*EMMC_INTERRUPT & INT_ERROR_MASK) && cnt--) wait_msec(1); 173 | return (cnt <= 0 || (*EMMC_INTERRUPT & INT_ERROR_MASK)) ? SD_ERROR : SD_OK; 174 | } 175 | 176 | /** 177 | * Wait for interrupt 178 | */ 179 | int sd_int(unsigned int mask) 180 | { 181 | unsigned int r, m=mask | INT_ERROR_MASK; 182 | int cnt = 1000000; while(!(*EMMC_INTERRUPT & m) && cnt--) wait_msec(1); 183 | r=*EMMC_INTERRUPT; 184 | if(cnt<=0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT) ) { *EMMC_INTERRUPT=r; return SD_TIMEOUT; } else 185 | if(r & INT_ERROR_MASK) { *EMMC_INTERRUPT=r; return SD_ERROR; } 186 | *EMMC_INTERRUPT=mask; 187 | return 0; 188 | } 189 | 190 | /** 191 | * Send a command 192 | */ 193 | int sd_cmd(unsigned int code, unsigned int arg) 194 | { 195 | int r=0; 196 | sd_err=SD_OK; 197 | if(code&CMD_NEED_APP) { 198 | r=sd_cmd(CMD_APP_CMD|(sd_rca?CMD_RSPNS_48:0),sd_rca); 199 | if(sd_rca && !r) { uart_puts("ERROR: failed to send SD APP command\n"); sd_err=SD_ERROR;return 0;} 200 | code &= ~CMD_NEED_APP; 201 | wait_msec(7); 202 | } 203 | if(sd_status(SR_CMD_INHIBIT)) { uart_puts("ERROR: EMMC busy\n"); sd_err= SD_TIMEOUT;return 0;} 204 | uart_puts("EMMC: Sending command ");uart_hex(code);uart_puts(" arg ");uart_hex(arg);uart_send('\n'); 205 | *EMMC_INTERRUPT=*EMMC_INTERRUPT; *EMMC_ARG1=arg; *EMMC_CMDTM=code; 206 | if(code==CMD_SEND_OP_COND) wait_msec(1000); else 207 | if(code==CMD_SEND_IF_COND || code==CMD_APP_CMD) wait_msec(100); 208 | if((r=sd_int(INT_CMD_DONE))) {uart_puts("ERROR: failed to send EMMC command\n");sd_err=r;return 0;} 209 | r=*EMMC_RESP0; 210 | if(code==CMD_GO_IDLE || code==CMD_APP_CMD) return 0; else 211 | if(code==(CMD_APP_CMD|CMD_RSPNS_48)) return r&SR_APP_CMD; else 212 | if(code==CMD_SEND_OP_COND) return r; else 213 | if(code==CMD_SEND_IF_COND) return r==arg? SD_OK : SD_ERROR; else 214 | if(code==CMD_ALL_SEND_CID) {r|=*EMMC_RESP3; r|=*EMMC_RESP2; r|=*EMMC_RESP1; return r; } else 215 | if(code==CMD_SEND_REL_ADDR) { 216 | sd_err=(((r&0x1fff))|((r&0x2000)<<6)|((r&0x4000)<<8)|((r&0x8000)<<8))&CMD_ERRORS_MASK; 217 | return r&CMD_RCA_MASK; 218 | } 219 | return r&CMD_ERRORS_MASK; 220 | // make gcc happy 221 | return 0; 222 | } 223 | 224 | /** 225 | * read a block from sd card and return the number of bytes read 226 | * returns 0 on error. 227 | */ 228 | int sd_readblock(unsigned int lba, unsigned char *buffer, unsigned int num) 229 | { 230 | int r,c=0,d; 231 | if(num<1) num=1; 232 | uart_puts("sd_readblock lba ");uart_hex(lba);uart_puts(" num ");uart_hex(num);uart_send('\n'); 233 | if(sd_status(SR_DAT_INHIBIT)) {sd_err=SD_TIMEOUT; return 0;} 234 | unsigned int *buf=(unsigned int *)buffer; 235 | if(sd_scr[0] & SCR_SUPP_CCS) { 236 | if(num > 1 && (sd_scr[0] & SCR_SUPP_SET_BLKCNT)) { 237 | sd_cmd(CMD_SET_BLOCKCNT,num); 238 | if(sd_err) return 0; 239 | } 240 | *EMMC_BLKSIZECNT = (num << 16) | 512; 241 | sd_cmd(num == 1 ? CMD_READ_SINGLE : CMD_READ_MULTI,lba); 242 | if(sd_err) return 0; 243 | } else { 244 | *EMMC_BLKSIZECNT = (1 << 16) | 512; 245 | } 246 | while( c < num ) { 247 | if(!(sd_scr[0] & SCR_SUPP_CCS)) { 248 | sd_cmd(CMD_READ_SINGLE,(lba+c)*512); 249 | if(sd_err) return 0; 250 | } 251 | if((r=sd_int(INT_READ_RDY))){uart_puts("\rERROR: Timeout waiting for ready to read\n");sd_err=r;return 0;} 252 | for(d=0;d<128;d++) buf[d] = *EMMC_DATA; 253 | c++; buf+=128; 254 | } 255 | if( num > 1 && !(sd_scr[0] & SCR_SUPP_SET_BLKCNT) && (sd_scr[0] & SCR_SUPP_CCS)) sd_cmd(CMD_STOP_TRANS,0); 256 | return sd_err!=SD_OK || c!=num? 0 : num*512; 257 | } 258 | 259 | /** 260 | * write a block to sd card and return the number of bytes written 261 | * returns 0 on error. 262 | */ 263 | int sd_writeblock(unsigned int lba, unsigned char *buffer, unsigned int num) 264 | { 265 | int r,c=0,d; 266 | if(num<1) num=1; 267 | uart_puts("sd_writeblock lba ");uart_hex(lba);uart_puts(" num ");uart_hex(num);uart_send('\n'); 268 | if(sd_status(SR_DAT_INHIBIT)) {sd_err=SD_TIMEOUT; return 0;} 269 | unsigned int *buf=(unsigned int *)buffer; 270 | if (((uint32_t) buf & 3) != 0) {uart_puts("\rERROR: bad aligned data\n");sd_err=0;return 0;} 271 | if(sd_scr[0] & SCR_SUPP_CCS) { 272 | if(num > 1 && (sd_scr[0] & SCR_SUPP_SET_BLKCNT)) { 273 | sd_cmd(CMD_SET_BLOCKCNT,num); 274 | if(sd_err) return 0; 275 | } 276 | *EMMC_BLKSIZECNT = (num << 16) | 512; 277 | sd_cmd(num == 1 ? CMD_WRITE_SINGLE : CMD_WRITE_MULTI,lba); 278 | if(sd_err) return 0; 279 | } else { 280 | *EMMC_BLKSIZECNT = (1 << 16) | 512; 281 | } 282 | while( c < num ) { 283 | if(!(sd_scr[0] & SCR_SUPP_CCS)) { 284 | sd_cmd(CMD_WRITE_SINGLE,(lba+c)*512); 285 | if(sd_err) return 0; 286 | } 287 | if((r=sd_int(INT_WRITE_RDY))){uart_puts("\rERROR: Timeout waiting for ready to write\n");sd_err=r;return 0;} 288 | for(d=0;d<128;d++) *EMMC_DATA = buf[d]; 289 | c++; buf+=128; 290 | } 291 | if((r=sd_int(INT_DATA_DONE))){uart_puts("\rERROR: Timeout waiting for done writing\n");sd_err=r;return 0;} 292 | if( num > 1 && !(sd_scr[0] & SCR_SUPP_SET_BLKCNT) && (sd_scr[0] & SCR_SUPP_CCS)) sd_cmd(CMD_STOP_TRANS,0); 293 | return sd_err!=SD_OK || c!=num? 0 : num*512; 294 | } 295 | 296 | /** 297 | * set SD clock to frequency in Hz 298 | */ 299 | int sd_clk(unsigned int f) 300 | { 301 | unsigned int d,c=41666666/f,x,s=32,h=0; 302 | int cnt = 100000; 303 | while((*EMMC_STATUS & (SR_CMD_INHIBIT|SR_DAT_INHIBIT)) && cnt--) wait_msec(1); 304 | if(cnt<=0) { 305 | uart_puts("ERROR: timeout waiting for inhibit flag\n"); 306 | return SD_ERROR; 307 | } 308 | 309 | *EMMC_CONTROL1 &= ~C1_CLK_EN; wait_msec(10); 310 | x=c-1; if(!x) s=0; else { 311 | if(!(x & 0xffff0000u)) { x <<= 16; s -= 16; } 312 | if(!(x & 0xff000000u)) { x <<= 8; s -= 8; } 313 | if(!(x & 0xf0000000u)) { x <<= 4; s -= 4; } 314 | if(!(x & 0xc0000000u)) { x <<= 2; s -= 2; } 315 | if(!(x & 0x80000000u)) { x <<= 1; s -= 1; } 316 | if(s>0) s--; 317 | if(s>7) s=7; 318 | } 319 | if(sd_hv>HOST_SPEC_V2) d=c; else d=(1<HOST_SPEC_V2) h=(d&0x300)>>2; 323 | d=(((d&0x0ff)<<8)|h); 324 | *EMMC_CONTROL1=(*EMMC_CONTROL1&0xffff003f)|d; wait_msec(10); 325 | *EMMC_CONTROL1 |= C1_CLK_EN; wait_msec(10); 326 | cnt=10000; while(!(*EMMC_CONTROL1 & C1_CLK_STABLE) && cnt--) wait_msec(10); 327 | if(cnt<=0) { 328 | uart_puts("ERROR: failed to get stable clock\n"); 329 | return SD_ERROR; 330 | } 331 | return SD_OK; 332 | } 333 | 334 | /** 335 | * initialize EMMC to read SDHC card 336 | */ 337 | int sd_init() 338 | { 339 | int r,cnt,ccs=0; 340 | // GPIO_CD 341 | r=IOREG(GPFSEL4); r&=~(7<<(7*3)); IOREG(GPFSEL4)=r; 342 | IOREG(GPPUD)=2; wait_msec(10); IOREG(GPPUDCLK1)=(1<<15); wait_msec(10); IOREG(GPPUD)=0; IOREG(GPPUDCLK1)=0; 343 | r=IOREG(GPHEN1); r|=1<<15; IOREG(GPHEN1)=r; 344 | 345 | // GPIO_CLK, GPIO_CMD 346 | r=IOREG(GPFSEL4); r|=(7<<(8*3))|(7<<(9*3)); IOREG(GPFSEL4)=r; 347 | IOREG(GPPUD)=2; wait_msec(10); IOREG(GPPUDCLK1)=(1<<16)|(1<<17); wait_msec(10); IOREG(GPPUD)=0; IOREG(GPPUDCLK1)=0; 348 | 349 | // GPIO_DAT0, GPIO_DAT1, GPIO_DAT2, GPIO_DAT3 350 | r=IOREG(GPFSEL5); r|=(7<<(0*3)) | (7<<(1*3)) | (7<<(2*3)) | (7<<(3*3)); IOREG(GPFSEL5)=r; 351 | IOREG(GPPUD)=2; wait_msec(10); 352 | IOREG(GPPUDCLK1)=(1<<18) | (1<<19) | (1<<20) | (1<<21); 353 | wait_msec(10); IOREG(GPPUD)=0; IOREG(GPPUDCLK1)=0; 354 | 355 | sd_hv = (*EMMC_SLOTISR_VER & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT; 356 | uart_puts("EMMC: GPIO set up\n"); 357 | // Reset the card. 358 | *EMMC_CONTROL0 = 0; *EMMC_CONTROL1 |= C1_SRST_HC; 359 | cnt=10000; do{wait_msec(10);} while( (*EMMC_CONTROL1 & C1_SRST_HC) && cnt-- ); 360 | if(cnt<=0) { 361 | uart_puts("ERROR: failed to reset EMMC\n"); 362 | return SD_ERROR; 363 | } 364 | uart_puts("EMMC: reset OK\n"); 365 | *EMMC_CONTROL1 |= C1_CLK_INTLEN | C1_TOUNIT_MAX; 366 | wait_msec(10); 367 | // Set clock to setup frequency. 368 | if((r=sd_clk(400000))) return r; 369 | *EMMC_INT_EN = 0xffffffff; 370 | *EMMC_INT_MASK = 0xffffffff; 371 | sd_scr[0]=sd_scr[1]=sd_rca=sd_err=0; 372 | sd_cmd(CMD_GO_IDLE,0); 373 | if(sd_err) return sd_err; 374 | 375 | sd_cmd(CMD_SEND_IF_COND,0x000001AA); 376 | if(sd_err) return sd_err; 377 | cnt=6; r=0; while(!(r&ACMD41_CMD_COMPLETE) && cnt--) { 378 | wait_msec(25); 379 | r=sd_cmd(CMD_SEND_OP_COND,ACMD41_ARG_HC); 380 | uart_puts("EMMC: CMD_SEND_OP_COND returned "); 381 | if(r&ACMD41_CMD_COMPLETE) 382 | uart_puts("COMPLETE "); 383 | if(r&ACMD41_VOLTAGE) 384 | uart_puts("VOLTAGE "); 385 | if(r&ACMD41_CMD_CCS) 386 | uart_puts("CCS "); 387 | uart_hex(r); 388 | uart_send('\n'); 389 | if(sd_err!=SD_TIMEOUT && sd_err!=SD_OK ) { 390 | uart_puts("ERROR: EMMC ACMD41 returned error\n"); 391 | return sd_err; 392 | } 393 | } 394 | if(!(r&ACMD41_CMD_COMPLETE) || !cnt ) return SD_TIMEOUT; 395 | if(!(r&ACMD41_VOLTAGE)) return SD_ERROR; 396 | if(r&ACMD41_CMD_CCS) ccs=SCR_SUPP_CCS; 397 | 398 | sd_cmd(CMD_ALL_SEND_CID,0); 399 | 400 | sd_rca = sd_cmd(CMD_SEND_REL_ADDR,0); 401 | uart_puts("EMMC: CMD_SEND_REL_ADDR returned "); 402 | uart_hex(sd_rca); 403 | uart_send('\n'); 404 | if(sd_err) return sd_err; 405 | 406 | // if((r=sd_clk(25000000))) return r; 407 | if((r=sd_clk(10400000))) return r; 408 | 409 | sd_cmd(CMD_CARD_SELECT,sd_rca); 410 | if(sd_err) return sd_err; 411 | 412 | if(sd_status(SR_DAT_INHIBIT)) return SD_TIMEOUT; 413 | *EMMC_BLKSIZECNT = (1<<16) | 8; 414 | sd_cmd(CMD_SEND_SCR,0); 415 | if(sd_err) return sd_err; 416 | if(sd_int(INT_READ_RDY)) return SD_TIMEOUT; 417 | 418 | r=0; cnt=100000; while(r<2 && cnt) { 419 | if( *EMMC_STATUS & SR_READ_AVAILABLE ) 420 | sd_scr[r++] = *EMMC_DATA; 421 | else 422 | wait_msec(1); 423 | } 424 | if(r!=2) return SD_TIMEOUT; 425 | if(sd_scr[0] & SCR_SD_BUS_WIDTH_4) { 426 | sd_cmd(CMD_SET_BUS_WIDTH,sd_rca|2); 427 | if(sd_err) return sd_err; 428 | *EMMC_CONTROL0 |= C0_HCTL_DWITDH; 429 | } 430 | // add software flag 431 | uart_puts("EMMC: supports "); 432 | if(sd_scr[0] & SCR_SUPP_SET_BLKCNT) 433 | uart_puts("SET_BLKCNT "); 434 | if(ccs) 435 | uart_puts("CCS "); 436 | uart_send('\n'); 437 | sd_scr[0]&=~SCR_SUPP_CCS; 438 | sd_scr[0]|=ccs; 439 | return SD_OK; 440 | } 441 | -------------------------------------------------------------------------------- /raspberrypi/sd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 bzt (bztsrc@github) 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #define SD_OK 0 27 | #define SD_TIMEOUT -1 28 | #define SD_ERROR -2 29 | 30 | #define SDCARD_BLOCK_SIZE 512 31 | 32 | int sd_init(); 33 | int sd_readblock(unsigned int lba, unsigned char *buffer, unsigned int num); 34 | int sd_writeblock(unsigned int lba, unsigned char *buffer, unsigned int num); 35 | -------------------------------------------------------------------------------- /raspberrypi/spi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "py/mpconfig.h" 5 | #include "py/mperrno.h" 6 | #include "bcm283x_spi.h" 7 | #include "rpi.h" 8 | #include "spi.h" 9 | 10 | void spi_init(spi_t *spi, int polarity, int phase) { 11 | // set GPIO2, GPIO3 to alternate function 0 12 | uint32_t reg = spi->CS & ~(CS_CS | CS_CPOL | CS_CPHA | CS_REN); 13 | if (polarity != 0) { 14 | reg |= CS_CPOL; 15 | } 16 | if (phase != 0) { 17 | reg |= CS_CPHA; 18 | } 19 | spi->CS = reg | CLEAR_TX | CLEAR_RX; 20 | spi->CLK = 833; // 250MHz/833 = 300KHz 21 | } 22 | 23 | void spi_deinit(spi_t *spi) { 24 | spi->CS = spi->CS & ~CS_TA; 25 | } 26 | 27 | void spi_chip_select(spi_t *spi, int cs) { 28 | spi->CS = (spi->CS & ~(CS_CS)) | (cs & 0x3U); 29 | } 30 | 31 | int spi_transfer(spi_t *spi, uint8_t *buf_tx, const uint32_t wlen, uint8_t *buf_rx, const uint32_t rlen, uint8_t padding) { 32 | int result; 33 | int len = (wlen > rlen) ? wlen : rlen; 34 | int txcnt = 0; 35 | int rxcnt = 0; 36 | 37 | spi->CS |= CLEAR_TX | CLEAR_RX; 38 | spi->CS = spi->CS | CS_TA; 39 | 40 | for(;;) { 41 | if (spi->CS & CS_TXD) { 42 | uint8_t data; 43 | if (txcnt < len) { 44 | if (txcnt < wlen) { 45 | data = *buf_tx++; 46 | } else { 47 | data = padding; 48 | } 49 | spi->FIFO = data; 50 | txcnt++; 51 | } 52 | } 53 | 54 | if (spi->CS & CS_RXD) { 55 | if (rxcnt < len) { 56 | uint8_t data = spi->FIFO; 57 | if (rxcnt < rlen) { 58 | *buf_rx++ = data; 59 | } 60 | rxcnt++; 61 | } 62 | } 63 | 64 | if ((txcnt == len) && (rxcnt == len) && (spi->CS & CS_DONE)) { 65 | result = len; 66 | break; 67 | } 68 | } 69 | spi->CS = spi->CS & ~CS_TA; 70 | return result; 71 | } 72 | 73 | void spi_set_clock_speed(spi_t *spi, uint32_t speed) { 74 | uint32_t val; 75 | uint32_t clk; 76 | clk = rpi_freq_core(); 77 | val = clk / speed; 78 | if (val * speed < clk) { 79 | val++; 80 | } 81 | spi->CLK = val; 82 | } 83 | 84 | uint32_t spi_get_clock_speed(spi_t *spi) { 85 | uint32_t val = spi->CLK; 86 | if (val < 2) { 87 | val = 65536; 88 | } 89 | return rpi_freq_core() / val; 90 | } 91 | -------------------------------------------------------------------------------- /raspberrypi/spi.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_SPI_H 2 | #define MICROPY_INCLUDED_RPI_SPI_H 3 | 4 | #include 5 | #include "bcm283x_spi.h" 6 | 7 | void spi_init(spi_t *spi, int polarity, int phase); 8 | void spi_deinit(spi_t *spi); 9 | 10 | void spi_set_clock_speed(spi_t *spi, uint32_t speed); 11 | uint32_t spi_get_clock_speed(spi_t *spi); 12 | 13 | void spi_chip_select(spi_t *spi, int cs); 14 | 15 | int spi_transfer(spi_t *spi, uint8_t *buf_tx, const uint32_t wlen, uint8_t *buf_rx, const uint32_t rlen, uint8_t padding); 16 | 17 | #endif // MICROPY_INCLUDED_RPI_SPI_H 18 | -------------------------------------------------------------------------------- /raspberrypi/start.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | .section .init 3 | 4 | _start: 5 | .ifndef RPI1 6 | // return to supervisor mode 7 | mrs r0, cpsr 8 | bic r0, r0, #0x1f 9 | orr r0, r0, #0x13 10 | msr spsr_cxsf, r0 11 | add r0, pc, #4 12 | msr ELR_hyp, r0 13 | eret 14 | .endif 15 | 16 | // stop core 1-3; QEMU only 17 | // mrc p15, #0, r1, c0, c0, #5 18 | // and r1, r1, #3 19 | // cmp r1, #2 20 | // bne halt 21 | 22 | // set IRQ_MODE stack 23 | ldr r0, =0x000000d2 24 | msr cpsr_c, r0 25 | ldr sp, =0x8000 26 | 27 | // set FIQ_MODE stack 28 | ldr r0, =0x000000d1 29 | msr cpsr_c, r0 30 | ldr sp, =0x4000 31 | 32 | // set mode to SVC_MODE 33 | ldr r0, =0x000000d3 34 | msr cpsr_c, r0 35 | ldr sp, =_estack 36 | 37 | 38 | // mrc p15, 0, r0, c1, c0, 0 39 | /// enable unaligned access support 40 | // orr r0, r0, #0x00400000 41 | /// enable data cache 42 | // orr r0, r0, #0x00000004 43 | /// enable instruction cache 44 | // orr r0, r0, #0x00001000 45 | /// enable branch prediction 46 | // orr r0, r0, #0x00000800 47 | // mcr p15, 0, r0, c1, c0, 0 48 | 49 | //enable fpu 50 | mrc p15, 0, r0, c1, c0, 2 51 | orr r0,r0,#0x300000 ;@ single precision 52 | orr r0,r0,#0xC00000 ;@ double precision 53 | mcr p15, 0, r0, c1, c0, 2 54 | mov r0,#0x40000000 55 | fmxr fpexc,r0 56 | 57 | // jump to main 58 | ldr r0, =0x00000000 59 | bl arm_main 60 | 61 | halt: 62 | b halt 63 | 64 | -------------------------------------------------------------------------------- /raspberrypi/uart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "py/mpconfig.h" 4 | #include "bcm283x_uart.h" 5 | #include "uart.h" 6 | 7 | #define IS_RX_RDY (!(uart0->FR & (1 << 4))) 8 | #define RX_CH (uart0->DR) 9 | #define IS_TX_RDY (!(uart0->FR & (1 << 5))) 10 | #define TX_CH(c) (uart0->DR = (c)) 11 | 12 | volatile uart_t *uart0; 13 | 14 | static void uart0_init_with_regs_addr(const uint32_t addr) { 15 | uart0 = (volatile uart_t *) addr; 16 | 17 | uart0->CR = 0; 18 | // set spped to 115200 bps 19 | uart0->IBRD = 1; 20 | uart0->FBRD = 40; 21 | // parity none 8bits FIFO enable 22 | uart0->LCRH = 0x70; 23 | 24 | uart0->CR = 0x0301; 25 | }; 26 | 27 | void uart0_qemu_init() { 28 | uart0_init_with_regs_addr(0x101F1000); 29 | } 30 | 31 | void uart0_putc(char c) { 32 | while(!IS_TX_RDY) { 33 | } 34 | TX_CH(c); 35 | } 36 | 37 | uint32_t uart0_getc(void) { 38 | uint32_t c; 39 | 40 | while (!IS_RX_RDY) { 41 | } 42 | c = RX_CH; 43 | return c & 0xffU; 44 | } 45 | 46 | uint32_t uart0_rx_state(void) { 47 | return IS_RX_RDY; 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /raspberrypi/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_UART_QEMU_H 2 | #define MICROPY_INCLUDED_RPI_UART_QEMU_H 3 | 4 | #include 5 | 6 | void uart0_qemu_init(); 7 | void uart0_putc(char c); 8 | uint32_t uart0_getc(void); 9 | uint32_t uart0_rx_state(void); 10 | 11 | #endif // MICROPY_INCLUDED_RPI_UART_QEMU_H 12 | -------------------------------------------------------------------------------- /raspberrypi/usbhost.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "usbd/usbd.h" 4 | 5 | #include "py/runtime.h" 6 | #include "mphalport.h" 7 | #include "bcm283x_mailbox.h" 8 | #include "vc_property.h" 9 | #include "usbhost.h" 10 | 11 | /* USB host controller driver static variables */ 12 | // memory block for these variables are allocated using 13 | // m_malloc() so we must keep them in MP object 14 | // to avoid them from deallocating by gc 15 | 16 | extern void *Core; 17 | extern void *Host; 18 | extern void *Power; 19 | extern void **Devices; 20 | extern void *databuffer; 21 | extern void **keyboards; 22 | extern void **mice; 23 | extern u32 RootHubDeviceNumber; 24 | 25 | 26 | extern hcd_globals_t *hcd_globals; 27 | static u32 usb_initialised = 0; 28 | 29 | void* MemoryAllocate(u32 length); 30 | void PowerOffUsb(); 31 | 32 | void rpi_usb_host_init(void) { 33 | if (usb_initialised == 0) { 34 | MP_STATE_PORT(hcd_globals) = MemoryAllocate(sizeof(hcd_globals_t)); 35 | UsbInitialise(); 36 | MP_STATE_PORT(hcd_globals)->core = Core; 37 | MP_STATE_PORT(hcd_globals)->host = Host; 38 | MP_STATE_PORT(hcd_globals)->power = Power; 39 | for (int i = 0; i < 32; i++) { 40 | MP_STATE_PORT(hcd_globals)->devices[i] = &Devices[i]; 41 | } 42 | MP_STATE_PORT(hcd_globals)->databuffer = databuffer; 43 | for (int i = 0; i < 4; i++) { 44 | MP_STATE_PORT(hcd_globals)->keyboards[i] = &keyboards[i]; 45 | MP_STATE_PORT(hcd_globals)->mice[i] = &mice[i]; 46 | } 47 | 48 | usb_initialised = 1; 49 | mp_hal_delay_ms(100); 50 | UsbCheckForChange(); 51 | mp_hal_delay_ms(100); 52 | UsbCheckForChange(); 53 | mp_hal_delay_ms(100); 54 | UsbCheckForChange(); 55 | mp_hal_delay_ms(100); 56 | UsbCheckForChange(); 57 | mp_hal_delay_ms(100); 58 | UsbCheckForChange(); 59 | } 60 | } 61 | 62 | void rpi_usb_host_process(void) { 63 | UsbCheckForChange(); 64 | } 65 | 66 | void rpi_usb_host_deinit(void) { 67 | if (usb_initialised != 0) { 68 | extern Result HcdStop(); 69 | HcdStop(); 70 | extern Result HcdDeinitialise(); 71 | HcdDeinitialise(); 72 | databuffer = NULL; 73 | RootHubDeviceNumber = 0; 74 | PowerOffUsb(); 75 | m_del(hcd_globals_t, MP_STATE_PORT(hcd_globals), 1); 76 | 77 | usb_initialised = 0; 78 | } 79 | } 80 | 81 | /* platform dependent functions called from functions in libcsud.a */ 82 | // defined in csud/include/platform/platform.h 83 | 84 | void LogPrint(const char* message, uint32_t messageLength) { 85 | printf(message); 86 | } 87 | 88 | void* MemoryReserve(u32 length, void* physicalAddress) { 89 | return physicalAddress; 90 | } 91 | 92 | void* MemoryAllocate(u32 length) { 93 | return m_new(uint8_t, length); 94 | } 95 | 96 | void MemoryDeallocate(void* address) { 97 | m_free(address); 98 | } 99 | 100 | void MemoryCopy(void* destination, void* source, u32 length) { 101 | memcpy(destination, source, length); 102 | } 103 | 104 | #define MB_SET_POWER_STATE (0x00028001) 105 | #define POWER_USBHCD (3) 106 | 107 | static Result power_usb(bool onoff){ 108 | u32 result; 109 | __attribute__((aligned(16))) u32 msg[] = { 110 | 0x20, // message length is 32 bytes 111 | 0, // this is a request 112 | MB_SET_POWER_STATE, // set power state tag 113 | 8, // the value length is 8 bytes 114 | 0, // this is a request 115 | POWER_USBHCD, // device id 116 | 3, // state value;bit0 = on, bit1=wait 117 | 0, // end tag 118 | }; 119 | 120 | if (onoff) { 121 | msg[6] = 3; 122 | } else { 123 | msg[6] = 2; 124 | } 125 | mailbox_write(MB_CH_PROP_ARM, (uint32_t) BUSADDR(msg) >> 4); 126 | mailbox_read(MB_CH_PROP_ARM); 127 | 128 | if ((msg[1] == MB_PROP_SUCCESS) && (msg[4] & MB_PROP_SUCCESS)) { 129 | result = OK; 130 | } else { 131 | result = ErrorDevice; 132 | } 133 | return result; 134 | } 135 | 136 | Result PowerOnUsb() { 137 | return power_usb(true); 138 | } 139 | 140 | void PowerOffUsb() { 141 | power_usb(false); 142 | } 143 | 144 | void MicroDelay(u32 delay) { 145 | mp_hal_delay_us(delay); 146 | } 147 | -------------------------------------------------------------------------------- /raspberrypi/usbhost.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_USBHOST_H 2 | #define MICROPY_INCLUDED_RPI_USBHOST_H 3 | 4 | typedef struct _hcd_globals_t { 5 | void *core; 6 | void *host; 7 | void *power; 8 | void *devices[32]; 9 | void *databuffer; 10 | void *keyboards[4]; 11 | void *mice[4]; 12 | } hcd_globals_t; 13 | 14 | void rpi_usb_host_init(void); 15 | void rpi_usb_host_process(void); 16 | void rpi_usb_host_deinit(void); 17 | 18 | #endif // MICROPY_INCLUDED_RPI_USBHOST_H 19 | -------------------------------------------------------------------------------- /raspberrypi/usbkbd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #ifdef MICROPY_HW_USBHOST 4 | #include "usbd/usbd.h" 5 | #include "device/hid/keyboard.h" 6 | 7 | #include "rpi.h" 8 | #include "usbkbd.h" 9 | 10 | 11 | #define USBKBD_KEYMAPSIZE (104) 12 | 13 | unsigned char keymap_us[2][USBKBD_KEYMAPSIZE] = { 14 | { 15 | 0x0, 0x1, 0x2, 0x3, 'a', 'b', 'c', 'd', 16 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 17 | 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 18 | 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', 19 | '3', '4', '5', '6', '7', '8', '9', '0', 20 | 0xd, 0x1b, 0x8, 0x9, ' ', '-', '=', '[', 21 | ']', '\\', 0x0, ';', '\'', '`', ',', '.', 22 | '/', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 23 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 24 | 0x0, 0x12, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x1c, 25 | 0x1d, 0x1f, 0x1e, 0x0, '/', '*', '-', '+', 26 | 0xd, '1', '2', '3', '4', '5', '6', '7', 27 | '8', '9', '0', '.', '\\', 0x0, 0x0, '=', 28 | }, 29 | { 30 | 0x0, 0x0, 0x0, 0x0, 'A', 'B', 'C', 'D', 31 | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 32 | 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 33 | 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', 34 | '#', '$', '%', '^', '&', '*', '(', ')', 35 | 0xa, 0x1b, '\b', '\t', ' ', '_', '+', '{', 36 | '}', '|', '~', ':', '"', '~', '<', '>', 37 | '?', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 38 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 39 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 40 | 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+', 41 | 0xa, '1', '2', '3', '4', '5', '6', '7', 42 | '8', '9', '0', '.', '|', 0x0, 0x0, '=', 43 | } 44 | }; 45 | 46 | unsigned char keymap_jp[2][USBKBD_KEYMAPSIZE] = { 47 | { 48 | 0x0, 0x1, 0x2, 0x3, 'a', 'b', 'c', 'd', 49 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 50 | 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 51 | 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', 52 | '3', '4', '5', '6', '7', '8', '9', '0', 53 | 0xd, 0x1b, 0x8, 0x9, ' ', '-', '^', '@', 54 | '[', 0x0, ']', ';', ':', 0x0, ',', '.', 55 | '/', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 56 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 57 | 0x0, 0x12, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x1c, 58 | 0x1d, 0x1f, 0x1e, 0x0, '/', '*', '-', '+', 59 | 0xd, '1', '2', '3', '4', '5', '6', '7', 60 | '8', '9', '0', '.', '\\', 0x0, 0x0, '=', 61 | }, 62 | { 63 | 0x0, 0x0, 0x0, 0x0, 'A', 'B', 'C', 'D', 64 | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 65 | 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 66 | 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '"', 67 | '#', '$', '%', '&', '\'', '(', ')', 0x0, 68 | 0xa, 0x1b, '\b', '\t', ' ', '=', '~', '`', 69 | '{', 0x0, '}', '+', '*', 0x0, '<', '>', 70 | '?', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 71 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 72 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 73 | 0x0, 0x0, 0x0, 0x0, '/', '*', '-', '+', 74 | 0xa, '1', '2', '3', '4', '5', '6', '7', 75 | '8', '9', '0', '.', '|', 0x0, 0x0, '=', 76 | } 77 | }; 78 | 79 | unsigned char keycode2char_us(int k, unsigned char shift) { 80 | if (k > 103) { 81 | return 0; 82 | } else { 83 | return keymap_us[(shift == 0) ? 0 : 1][k]; 84 | } 85 | } 86 | 87 | unsigned char keycode2char_jp(int k, unsigned char shift) { 88 | k = k & 0xff; 89 | if (k < 104) { 90 | return keymap_jp[(shift == 0) ? 0 : 1][k]; 91 | } else if (k == 135) { 92 | return (shift == 0) ? '\\' : '_'; 93 | } else if (k == 137) { 94 | return (shift == 0) ? '\\' : '|'; 95 | } else { 96 | return 0; 97 | } 98 | } 99 | 100 | void usbkbd_init(usbkbd_t *kbd) { 101 | kbd->kbd_addr = 0; 102 | for (int i = 0; i < 6; i++) { 103 | kbd->keys[i] = 0; 104 | } 105 | kbd->keycode2char = keycode2char_us; 106 | } 107 | 108 | // usbkbd_getc() returns -1 if no input 109 | int usbkbd_getc(usbkbd_t *kbd) { 110 | unsigned int key; 111 | struct KeyboardModifiers mod; 112 | int result = -1; 113 | 114 | if (kbd->kbd_addr == 0) { 115 | // Is there a keyboard ? 116 | UsbCheckForChange(); 117 | if (KeyboardCount() > 0) { 118 | kbd->kbd_addr = KeyboardGetAddress(0); 119 | } 120 | } 121 | 122 | if (kbd->kbd_addr != 0) { 123 | for(int i = 0; i < 6; i++) { 124 | // Read and print each keycode of pressed keys 125 | key = KeyboardGetKeyDown(kbd->kbd_addr, i); 126 | if (key != kbd->keys[0] && key != kbd->keys[1] && \ 127 | key != kbd->keys[2] && key != kbd->keys[3] && \ 128 | key != kbd->keys[4] && key != kbd->keys[5] && key) { 129 | mod = KeyboardGetModifiers(kbd->kbd_addr); 130 | if (mod.RightControl | mod.LeftControl) { 131 | unsigned char c = (*(kbd->keycode2char))(key, 1); 132 | switch(c) { 133 | case 'A': result = 1; break; 134 | case 'B': result = 2; break; 135 | case 'C': result = 3; break; 136 | case 'D': result = 4; break; 137 | case 'E': result = 5; break; 138 | case 'F': result = 6; break; 139 | case 'K': result = 11; break; 140 | case 'N': result = 14; break; 141 | case 'P': result = 16; break; 142 | case 'U': result = 21; break; 143 | default: result = 0; 144 | } 145 | } else { 146 | result = (*(kbd->keycode2char))(key, mod.RightShift | mod.LeftShift); 147 | // convert arrow keys to EMACS binding controls 148 | switch(result) { 149 | case 0x1d: result = 2; break; 150 | case 0x1c: result = 6; break; 151 | case 0x1f: result = 14; break; 152 | case 0x1e: result = 16; break; 153 | default: break; 154 | } 155 | } 156 | } 157 | kbd->keys[i] = key; 158 | } 159 | 160 | if (KeyboardPoll(kbd->kbd_addr) != 0) { 161 | kbd->kbd_addr = 0; 162 | } 163 | } 164 | return result; 165 | } 166 | #endif 167 | 168 | -------------------------------------------------------------------------------- /raspberrypi/usbkbd.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_USBKBD_H 2 | #define MICROPY_INCLUDED_RPI_USBKBD_H 3 | 4 | #ifdef MICROPY_HW_USBHOST 5 | 6 | typedef unsigned char (*f_keycode2char_t)(int k, unsigned char shift); 7 | 8 | typedef struct _usbkbd_t { 9 | unsigned int kbd_addr; 10 | unsigned int keys[6]; 11 | f_keycode2char_t keycode2char; 12 | } usbkbd_t; 13 | 14 | unsigned char keycode2char_us(int k, unsigned char shift); 15 | unsigned char keycode2char_jp(int k, unsigned char shift); 16 | 17 | void usbkbd_init(usbkbd_t *kbd); 18 | int usbkbd_getc(usbkbd_t *kbd); 19 | 20 | #endif 21 | 22 | #endif // MICROPY_INCLUDED_RPI_USBKBD_H 23 | -------------------------------------------------------------------------------- /raspberrypi/vc_property.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "vc_property.h" 3 | 4 | // required buffer size in bytes (read buffer size or write buffer size) 5 | // -1 means buffer is variable length 6 | // -2 for error 7 | int vc_property_length(unsigned int property) { 8 | int result; 9 | switch(property) { 10 | case 0x00048001: 11 | result = 0; 12 | break; 13 | case 0x00000001: 14 | case 0x00010001: 15 | case 0x00010002: 16 | case 0x00060001: 17 | case 0x0003000d: 18 | case 0x0003000e: 19 | case 0x0003000f: 20 | case 0x00040002: 21 | case 0x00040005: 22 | case 0x00044005: 23 | case 0x00048005: 24 | case 0x00040006: 25 | case 0x00044006: 26 | case 0x00048006: 27 | case 0x00040007: 28 | case 0x00044007: 29 | case 0x00048007: 30 | case 0x00040008: 31 | result = 4; 32 | break; 33 | case 0x00010003: 34 | result = 6; 35 | break; 36 | case 0x00010004: 37 | case 0x00010005: 38 | case 0x00010006: 39 | case 0x00020001: 40 | case 0x00020002: 41 | case 0x00028001: 42 | case 0x00030001: 43 | case 0x00038001: 44 | case 0x00030002: 45 | case 0x00030004: 46 | case 0x00030007: 47 | case 0x00030009: 48 | case 0x00038009: 49 | case 0x00030003: 50 | case 0x00038003: 51 | case 0x00030005: 52 | case 0x00030008: 53 | case 0x00030006: 54 | case 0x0003000a: 55 | case 0x00030014: 56 | case 0x00040001: 57 | case 0x00040003: 58 | case 0x00044003: 59 | case 0x00048003: 60 | case 0x00040004: 61 | case 0x00044004: 62 | case 0x00048004: 63 | case 0x00040009: 64 | case 0x00044009: 65 | case 0x00048009: 66 | result = 8; 67 | break; 68 | case 0x00038002: 69 | case 0x0003000c: 70 | result = 12; 71 | break; 72 | case 0x0004000a: 73 | case 0x0004400a: 74 | case 0x0004800a: 75 | case 0x00008011: 76 | result = 16; 77 | break; 78 | case 0x00008010: 79 | result = 24; 80 | break; 81 | case 0x00030010: 82 | result = 28; 83 | break; 84 | case 0x00030020: 85 | result = 136; 86 | break; 87 | case 0x0004000b: 88 | result = 1024; 89 | break; 90 | case 0x00010007: 91 | case 0x00050001: 92 | case 0x0004400b: 93 | case 0x0004800b: 94 | result = -1; 95 | break; 96 | default : 97 | result = -2; 98 | } 99 | return result; 100 | } 101 | -------------------------------------------------------------------------------- /raspberrypi/vc_property.h: -------------------------------------------------------------------------------- 1 | #ifndef MICROPY_INCLUDED_RPI_VC_PROP_H 2 | #define MICROPY_INCLUDED_RPI_VC_PROP_H 3 | 4 | // mailbox request / response code 5 | #define MB_PROP_REQUEST (0) 6 | #define MB_PROP_SUCCESS (0x80000000) 7 | 8 | // Subjects 9 | #define PROP_FIRMWARE 0x00000000 10 | #define PROP_HARDWARE 0x00010000 11 | #define PROP_POWER 0x00020000 12 | #define PROP_CLOCK 0x00030000 13 | #define PROP_VOLTAGE 0x00030000 14 | #define PROP_TEMP 0x00030000 15 | #define PROP_GPU 0x00030000 16 | #define PROP_FRAMEBUF 0x00040000 17 | #define PROP_CMDLINE 0x00050000 18 | #define PROP_DMACHAN 0x00060000 19 | 20 | // Cursor Info (set only) 21 | #define PROP_CRSRINFO 0x00008010 22 | #define PROP_CRSRSTAT 0x00008011 23 | 24 | // Commands 25 | #define PROP_GET 0x00000000 26 | #define PROP_TEST 0x00004000 27 | #define PROP_SET 0x00008000 28 | 29 | // Arguments 30 | // Firmware 31 | #define PROP_VERSION 1 32 | 33 | // Hardware 34 | #define PROP_REVISION 2 35 | #define PROP_MACADDR 3 36 | #define PROP_SERIAL 4 37 | #define PROP_ARM_MEM 5 38 | #define PROP_VC_MEM 6 39 | #define PROP_ALLCLOCK 7 40 | 41 | // Power 42 | #define PROP_STATE 1 43 | #define PROP_TIMING 2 44 | 45 | // Clock 46 | #define PROP_RATE 2 47 | #define PROP_MAXRATE 4 48 | #define PROP_MINRATE 7 49 | #define PROP_TURBO 9 50 | 51 | // Voltage 52 | #define PROP_CUR_V 3 53 | #define PROP_MAX_V 5 54 | #define PROP_MIN_V 8 55 | 56 | // GPU 57 | #define PROP_CUR_TEMP 6 58 | #define PROP_MAX_TEMP 10 59 | #define PROP_ALLOCMEM 12 60 | #define PROP_LOCKMEM 13 61 | #define PROP_UNLOCKMEM 14 62 | #define PROP_FREEMEM 15 63 | #define PROP_DISPMANX 20 64 | #define PROP_EDID 32 65 | 66 | // Frame buffer 67 | #define PROP_BUFADDR 1 68 | #define PROP_BLANK 2 69 | #define PROP_PHYSSIZE 3 70 | #define PROP_VIRTSIZE 4 71 | #define PROP_BITDEPTH 5 72 | #define PROP_PXLORDER 6 73 | #define PROP_ALPHA 7 74 | #define PROP_PITCH 8 75 | #define PROP_OFFSET 9 76 | #define PROP_OVERSCAN 10 77 | #define PROP_PALETTE 11 78 | 79 | int vc_property_length(unsigned int property); 80 | 81 | #endif // MICROPY_INCLUDED_RPI_VC_PROP_H 82 | --------------------------------------------------------------------------------