URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/openarty/trunk/sw
- from Rev 35 to Rev 36
- ↔ Reverse comparison
Rev 35 → Rev 36
/board/Makefile
31,11 → 31,12
## |
## |
.PHONY: all |
all: exstartup oledtest gpsdump |
PROGRAMS := exstartup oledtest gpsdump exmulti |
all: $(PROGRAMS) |
OBJDIR := obj-zip |
CC := zip-gcc |
OBJDUMP := zip-objdump |
SOURCES := exstartup.c bootloader.c gpsdump.c oledtest.c |
SOURCES := exstartup.c bootloader.c gpsdump.c oledtest.c exmulti.c |
HEADERS := artyboard.h zipsys.h |
# |
# For source analysis, the following macros are defined: |
44,7 → 45,7
|
%.o: $(OBJDIR)/%.o |
$(OBJDIR)/%.o: %.c |
$(CC) -c -fno-builtin $< -o $@ |
$(CC) -O3 -c -fno-builtin $< -o $@ |
%.txt: % |
$(OBJDUMP) -S -D $^ > $@ |
|
53,13 → 54,16
gpsdump: $(OBJDIR)/gpsdump.o $(OBJDIR)/bootloader.o arty.ld |
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=gpsdump.map $(OBJDIR)/gpsdump.o $(OBJDIR)/bootloader.o -o $@ |
oledtest: $(OBJDIR)/oledtest.o $(OBJDIR)/bootloader.o $(OBJDIR)/splash.o $(OBJDIR)/mug.o arty.ld |
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=gpsdump.map $(OBJDIR)/oledtest.o $(OBJDIR)/bootloader.o $(OBJDIR)/splash.o $(OBJDIR)/mug.o -o $@ |
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=oledtest.map $(OBJDIR)/oledtest.o $(OBJDIR)/bootloader.o $(OBJDIR)/splash.o $(OBJDIR)/mug.o -o $@ |
|
exmulti: $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o arty.ld |
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=exmulti.map $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o -o $@ |
|
exstartup.txt: exstartup |
$(OBJDUMP) -S -D $^ > $@ |
|
clean: |
rm -f exstartup exstartup.map exstartup.txt |
rm -rf $(PROGRAMS) $(addsuffix .map,$(PROGRAMS)) $(addsuffix .txt,$(PROGRAMS)) |
rm -rf $(OBJDIR)/ |
|
define build-depends |
/board/artyboard.h
57,6 → 57,23
#define BUS_SDCARD 0x1000 |
#define BUS_OLED 0x2000 |
#define BUS_ZIP 0x4000 |
|
// DMA Interrupt parameters |
#define DMA_JIFFIES (DMA_TRIGGER|0x0400) |
#define DMA_TMC (DMA_TRIGGER|0x0800) |
#define DMA_TMB (DMA_TRIGGER|0x0c00) |
#define DMA_TMA (DMA_TRIGGER|0x1000) |
#define DMA_AUX (DMA_TRIGGER|0x1400) |
#define DMA_PPS (DMA_TRIGGER|0x1800) |
#define DMA_NETRX (DMA_TRIGGER|0x1c00) |
#define DMA_NETTX (DMA_TRIGGER|0x2000) |
#define DMA_UARTRX (DMA_TRIGGER|0x2400) |
#define DMA_UARTTX (DMA_TRIGGER|0x2800) |
#define DMA_GPSRX (DMA_TRIGGER|0x2c00) |
#define DMA_GPSTX (DMA_TRIGGER|0x3000) |
#define DMA_SDCARD (DMA_TRIGGER|0x3400) |
#define DMA_OLED (DMA_TRIGGER|0x3800) |
|
// That's our maximum number of interrupts. Any more, and we'll need to |
// remove one. Don't forget, the primary interrupt source will be the SYS_ |
// interrupts, and there's another set of AUX_ interrupts--both available if |
84,7 → 101,7
|
typedef struct { |
volatile unsigned rxcmd, txcmd; |
volatile long mac; |
volatile unsigned mac[2]; |
volatile unsigned rxmiss, rxerr, rxcrc, txcol; |
#define ENET_TXGO 0x004000 |
#define ENET_TXBUSY 0x004000 |
139,7 → 156,8
volatile unsigned io_gpio; |
volatile unsigned io_uart_rx, io_uart_tx; |
volatile unsigned io_gps_rx, io_gps_tx; |
unsigned io_reserved[32-18]; |
volatile unsigned io_gps_sec, io_gps_sub, io_gps_step; |
unsigned io_reserved[32-21]; |
SCOPE io_scope[4]; |
RTC io_rtc; |
SDCARD io_sd; |
/board/bootloader.c
96,6 → 96,41
#include "artyboard.h" |
#include "zipsys.h" |
|
// A bootloader is about nothing more than copying memory from a couple |
// particular locations (Flash/ROM) to other locations in memory (BLKRAM |
// and SDRAM). Our DMA is a hardware accelerator that does nothing but |
// copy memory from one location to another. Why not use the DMA for this |
// purpose then? |
// |
// Here, we have a USE_DMA #define. When this is defined, the memory copy |
// will be done using the DMA hardware accelerator. This is a good thing, |
// and this should be defined. There are two problems with defining this |
// however: 1) It obscures for any readers of this code what is actually |
// happening, and 2) it makes the code dependent upon yet another piece of the |
// hardware design working. For these reasons, we allow you to turn it off. |
#define USE_DMA |
|
// |
// _start: |
// |
// Every computer needs to start processing from somewhere on reboot, and every |
// program needs some entry point. For the ZipCPU, that starting place is the |
// routine with the _start symbol. It is important that this start symbol be |
// placed at the boot address for the CPU. This is the very first address of |
// program memory, and (currently) on the Arty board it is placed in Flash at |
// _start = 0x4e0000. To make certain this routine goes into the very first |
// address in flash, we place it into it's own special section, the .start |
// section, and then tell the linker that the .start section is the first |
// section where it needs to start placing code. |
// |
// If you read through this short assembly routine below, you'll find that it |
// does only a small number of tasks. It sets the stack pointer to point to |
// the top of the stack (a symbol defined in the linker file), calls the |
// bootloader, resets the stack pointer, clears any data cache, and then calls |
// the kernel entry function. It also sets up a return address for the kernel |
// entry function so that, should the kernel ever exit, it wouldn't exit on |
// any error but rather it would exit by halting the CPU. |
// |
asm("\t.section\t.start\n" |
"\t.global\t_start\n" |
"_start:\n" |
116,18 → 151,33
_blkram, _flash, _bss_image_end, |
_kernel_image_start, _kernel_image_end; |
|
// |
// We need to insist that the bootloader be kept in Flash, else it would depend |
// upon running a routine from memory that ... wasn't in memory yet. For this |
// purpose, we place the bootloader in a special .boot section. We'll also tell |
// the linker, via the arty.ld file, that thsi .boot section needs to be placed |
// into flash. |
// |
extern void bootloader(void) __attribute__ ((section (".boot"))); |
|
// #define USE_DMA |
// |
// bootloader() |
// |
// Here's the actual boot loader itself. It copies three areas from flash: |
// 1. An area from flash to block RAM |
// 2. A second area from flash to SDRAM |
// 3. The third area isn't copied from flash, but rather it is just set to |
// zero. This is sometimes called the BSS segment. |
// |
void bootloader(void) { |
int zero = 0; |
|
#ifdef USE_DMA |
zip->dma.ctrl= DMACLEAR; |
zip->dma.rd = _kernel_image_start; |
if (_kernel_image_end != _sdram_image_start) { |
zip->dma.len = _kernel_image_end - _blkram; |
zip->dma.wr = _blkram; |
zip->dma.rd = &_kernel_image_start; |
if (&_kernel_image_end != &_sdram_image_start) { |
zip->dma.len = &_kernel_image_end - &_blkram; |
zip->dma.wr = &_blkram; |
zip->dma.ctrl= DMACCOPY; |
|
zip->pic = SYSINT_DMAC; |
135,16 → 185,19
; |
} |
|
zip->dma.len = &_sdram_image_end - _sdram; |
zip->dma.wr = _sdram; |
zip->dma.ctrl= DMACCOPY; |
// zip->dma.rd // Keeps the same value |
zip->dma.wr = &_sdram; |
if (&_sdram_image_end != &_sdram) { |
zip->dma.len = &_sdram_image_end - &_sdram; |
zip->dma.ctrl= DMACCOPY; |
} |
|
zip->pic = SYSINT_DMAC; |
while((zip->pic & SYSINT_DMAC)==0) |
; |
|
if (_bss_image_end != _sdram_image_end) { |
zip->dma.len = _bss_image_end - _sdram_image_end; |
if (&_bss_image_end != &_sdram_image_end) { |
zip->dma.len = &_bss_image_end - &_sdram_image_end; |
zip->dma.rd = &zero; |
// zip->dma.wr // Keeps the same value |
zip->dma.ctrl = DMACCOPY; |
/board/exmulti.c
0,0 → 1,372
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: exmulti.c |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: Very similar to exstartup.c, the purpose of this program is to |
// demonstrate several working peripherals. To the exstartup |
// peripherals, we'll add the GPS and the GPS PPS tracking. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include "artyboard.h" |
#include "zipsys.h" |
|
void idle_task(void) { |
while(1) |
zip_idle(); |
} |
|
void wait_on_interrupt(int mask) { |
zip->pic = DALLPIC|mask; |
zip->pic = EINT(mask); |
zip_rtu(); |
} |
|
int user_stack[256]; |
void user_task(void) { |
const unsigned white = 0x070707, black = 0; |
while(1) { |
unsigned btn, subnow, sw; |
|
subnow = (sys->io_gps_sub >> 28)&0x0f; |
|
// If the button is pressed, toggle the LED |
// Otherwise, turn the LED off. |
// |
|
// First, get all the pressed buttons |
btn = (sys->io_btnsw) & 0x0f0; |
// Now, acknowledge the button presses that we just read |
sys->io_btnsw = btn; |
btn >>= 4; |
|
// Now, use the time as the toggle function. |
btn = (subnow ^ btn)&btn & 0x07; |
|
sys->io_ledctrl = btn | 0x070; |
|
sw = sys->io_btnsw & 0x0f; |
for(int i=0; i<4; i++) |
sys->io_clrled[i] = (sw & (1<<i)) ? white : black; |
|
} |
} |
|
int mpyuhi(int a, int b) { |
// err_in_ns = mpyuhi(err_in_ns, err); |
// __asm__("MPYUHI %1,%0" :"+r"(a):"r"(b)); |
unsigned alo, blo, ahi, bhi, f, o, i, l, rhi; |
|
alo = (a & 0x0ffff); |
ahi = (a >> 16)&0x0ffff; |
blo = (b & 0x0ffff); |
bhi = (b >> 16)&0x0ffff; |
|
l = alo * blo; |
o = ahi * blo; |
i = alo * bhi; |
f = ahi * bhi; |
|
rhi = o + i + (l >> 16); |
return (rhi >> 16) + f; |
// return f; |
// return ahi; |
} |
|
int hexdigit(int v) { |
if (v < 10) |
return v + '0'; |
else |
return v + 'A' - 10; |
} |
|
int errstring[128]; |
|
void entry(void) { |
const unsigned red = 0x0ff0000, green = 0x0ff00, blue = 0x0ff, |
white = 0x070707, black = 0, dimgreen = 0x1f00, |
second = 81250000; |
int i, sw; |
|
// Start the GPS converging ... |
sys->io_gps.g_alpha = 2; |
sys->io_gps.g_beta = 0x14bda12f; |
sys->io_gps.g_gamma = 0x1f533ae8; |
|
int user_context[16]; |
for(i=0; i<15; i++) |
user_context[i] = 0; |
user_context[15] = (unsigned)idle_task; |
zip_restore_context(user_context); |
|
for(i=0; i<4; i++) |
sys->io_clrled[i] = red; |
sys->io_ledctrl = 0x0ff; |
|
// Clear the PIC |
// |
// Acknowledge all interrupts, turn off all interrupts |
// |
zip->pic = 0x7fff7fff; |
while(sys->io_pwrcount < (second >> 4)) |
; |
|
// Repeating timer, every 250ms |
zip->tma = (second/4) | 0x80000000; |
wait_on_interrupt(SYSINT_TMA); |
|
sys->io_clrled[0] = green; |
sys->io_ledctrl = 0x010; |
|
wait_on_interrupt(SYSINT_TMA); |
|
sys->io_clrled[0] = dimgreen; |
sys->io_clrled[1] = green; |
sys->io_scope[0].s_ctrl = 32 | 0x80000000; // SCOPE_TRIGGER; |
sys->io_ledctrl = 0x020; |
|
wait_on_interrupt(SYSINT_TMA); |
|
sys->io_clrled[1] = dimgreen; |
sys->io_clrled[2] = green; |
sys->io_ledctrl = 0x040; |
|
wait_on_interrupt(SYSINT_TMA); |
|
sys->io_clrled[2] = dimgreen; |
sys->io_clrled[3] = green; |
sys->io_ledctrl = 0x080; |
|
wait_on_interrupt(SYSINT_TMA); |
|
sys->io_clrled[3] = dimgreen; |
|
wait_on_interrupt(SYSINT_TMA); |
|
for(i=0; i<4; i++) |
sys->io_clrled[i] = black; |
|
// Wait one second ... |
for(i=0; i<4; i++) |
wait_on_interrupt(SYSINT_TMA); |
|
// Blink all the LEDs |
// First turn them on |
sys->io_ledctrl = 0x0ff; |
// Then wait a quarter second |
wait_on_interrupt(SYSINT_TMA); |
// Then turn the back off |
sys->io_ledctrl = 0x0f0; |
// and wait another quarter second |
wait_on_interrupt(SYSINT_TMA); |
|
// Now, read buttons, and flash an LED on any button being held |
// down ... ? neat? |
|
// Now, let's synchronize ourselves to the PPS |
user_context[13] = (int)&user_stack[256]; |
user_context[15] = (int)&user_task; |
zip_restore_context(user_context); |
|
do { |
wait_on_interrupt(SYSINT_PPS|SYSINT_TMA); |
} while((zip->pic & SYSINT_PPS)==0); |
|
while(1) { |
int *s = errstring; |
|
zip->wdt = CLOCKFREQ_HZ*4; |
sys->io_ledctrl = 0x088; |
|
// 1. Read and report the GPS tracking err |
|
// Get the upper 32-bits of the error; |
int err = *(int *)(&sys->io_gpstb.tb_err); |
int err_in_ns; |
/* |
long err_in_ns_long = err; |
err_in_ns_long *= 1000000000l; |
err_in_ns_long >>= 32; |
int err_in_ns = (int)(err_in_ns_long); |
*/ |
int err_sgn = (err < 0)?1:0; |
err_in_ns = (err<0)?-err:err; |
err_in_ns = mpyuhi(err_in_ns, 1000000000); |
int digit; |
|
|
*s++ = '\r'; |
*s++ = '\n'; |
*s++ = 'G'; |
*s++ = 'P'; |
*s++ = 'S'; |
*s++ = ' '; |
*s++ = 'P'; |
*s++ = 'P'; |
*s++ = 'S'; |
*s++ = ' '; |
*s++ = 'E'; |
*s++ = 'r'; |
*s++ = 'r'; |
*s++ = ':'; |
*s++ = ' '; |
|
|
*s++ = '0'; |
*s++ = 'x'; |
*s++ = hexdigit((err>>28)&0x0f); |
*s++ = hexdigit((err>>24)&0x0f); |
*s++ = hexdigit((err>>20)&0x0f); |
*s++ = hexdigit((err>>16)&0x0f); |
*s++ = hexdigit((err>>12)&0x0f); |
*s++ = hexdigit((err>> 8)&0x0f); |
*s++ = hexdigit((err>> 4)&0x0f); |
*s++ = hexdigit((err )&0x0f); |
|
*s++ = ' '; |
*s++ = '='; |
*s++ = '>'; |
*s++ = ' '; |
|
*s++ = '0'; |
*s++ = 'x'; |
*s++ = hexdigit((err_in_ns>>28)&0x0f); |
*s++ = hexdigit((err_in_ns>>24)&0x0f); |
*s++ = hexdigit((err_in_ns>>20)&0x0f); |
*s++ = hexdigit((err_in_ns>>16)&0x0f); |
*s++ = hexdigit((err_in_ns>>12)&0x0f); |
*s++ = hexdigit((err_in_ns>> 8)&0x0f); |
*s++ = hexdigit((err_in_ns>> 4)&0x0f); |
*s++ = hexdigit((err_in_ns )&0x0f); |
|
*s++ = ' '; |
*s++ = '='; |
*s++ = '>'; |
*s++ = ' '; |
|
*s++ = (err_sgn)?'-':' '; |
// Milliseconds |
digit = err_in_ns / 100000000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 100000000; |
// |
digit = err_in_ns / 10000000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 10000000; |
// |
digit = err_in_ns / 1000000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 1000000; |
// Micro seconds |
digit = err_in_ns / 100000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 100000; |
// |
digit = err_in_ns / 10000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 10000; |
// |
digit = err_in_ns / 1000; |
*s++ = digit+'0'; |
err_in_ns -= digit * 1000; |
// Nano seconds |
*s++ = '.'; |
digit = err_in_ns / 100; |
*s++ = digit+'0'; |
err_in_ns -= digit * 100; |
// |
digit = err_in_ns / 10; |
*s++ = digit+'0'; |
err_in_ns -= digit * 10; |
// |
digit = err_in_ns; |
*s++ = digit+'0'; |
// |
*s++ = ' '; |
*s++ = 'u'; |
*s++ = 'S'; |
*s++ = '\r'; |
*s++ = '\n'; |
*s++ = '\r'; |
*s++ = '\n'; |
*s++ = '\0'; |
|
/* |
zip->dma.ctrl = DMACLEAR; |
zip->dma.rd = errstring; |
zip->dma.wr = &sys->io_uart_tx; |
zip->dma.len = s - errstring-1; |
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_GPSRX); |
wait_on_interrupt(SYSINT_DMAC); |
*/ |
|
for(int i=0; errstring[i]; i++) { |
wait_on_interrupt(SYSINT_UARTTX); |
sys->io_uart_tx = errstring[i]; |
zip->pic = SYSINT_UARTTX; |
} |
|
sys->io_ledctrl = 0x080; |
|
/* |
zip->dma.rd = &sys->io_gps_rx; |
zip->dma.wr = &sys->io_uart_tx; |
zip->dma.len = 0x01000000; |
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_GPSRX); |
wait_on_interrupt(SYSINT_PPS); |
*/ |
|
/* |
if (zip_ucc() & CC_FAULT) { |
zip_save_context(user_context); |
user_context[14] = CC_GIE; |
user_context[15] = (int)&idle_task; |
zip_restore_context(user_context); |
} |
*/ |
|
zip->pic = SYSINT_GPSRX | SYSINT_PPS; |
do { |
wait_on_interrupt(SYSINT_PPS|SYSINT_GPSRX); |
if (zip->pic & SYSINT_GPSRX) { |
sys->io_uart_tx = sys->io_gps_rx; |
zip->pic = SYSINT_GPSRX; |
} |
} while((zip->pic & SYSINT_PPS)==0); |
|
// wait_on_interrupt(SYSINT_PPS); |
// zip->dma.ctrl= DMACLEAR; |
} |
|
zip_halt(); |
} |
|
/board/exstartup.c
1,3 → 1,42
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: exstartup.c |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: A fun example program that runs on the Arty, just to show |
// that the minimum set of peripherals (LEDs, color LEDs, buttons, |
// switches, etc.) work. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include "artyboard.h" |
#include "zipsys.h" |
|
/board/gpsdump.c
35,9 → 35,12
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include "zipsys.h" |
#include "artyboard.h" |
|
void entry(void) { |
/* |
// Method one: direct polling |
while(1) { |
int ch; |
ch = sys->io_gps_rx; |
44,4 → 47,29
if ((ch&-256)==0) |
sys->io_uart_tx = ch; |
} |
*/ |
// Method two: Waiting on interrupts |
zip->pic = SYSINT_GPSRX; |
while(1) { |
while((zip->pic & SYSINT_GPSRX)==0) |
; |
sys->io_uart_tx = sys->io_gps_rx; |
zip->pic = SYSINT_GPSRX; |
} |
|
/* |
// Method three: Use the DMA |
zip->dma.ctrl = DMACLEAR; |
while(1) { |
zip->dma.rd = &sys->io_gps_rx; |
zip->dma.wr = &sys->io_uart_tx; |
zip->dma.len = 0x01000000; // More than we'll ever do ... |
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_GPSRX); |
// zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC); |
|
while(zip->dma.ctrl & 0x80000000) |
if (zip->dma.ctrl & 0x40000000) |
zip_halt();; |
} |
*/ |
} |
/board/oledtest.c
40,8 → 40,8
// |
// |
|
#include "zipsys.h" |
#include "artyboard.h" |
#include "zipsys.h" |
|
void idle_task(void) { |
while(1) |
89,6 → 89,13
} // else anything less has likely already passed |
} |
|
void wait_on_interrupt(int mask) { |
// Clear our interrupt only, but disable all others |
zip->pic = DALLPIC|mask; |
zip->pic = EINT(mask); |
zip_rtu(); |
zip->pic = DINT(mask)|mask; |
} |
|
void oled_clear(void); |
|
260,6 → 267,24
; |
} |
|
void oled_show_image(int *img) { |
#define USE_DMA |
#ifdef USE_DMA |
zip->dma.ctrl = DMACLEAR; |
zip->dma.rd = img; |
zip->dma.wr = &sys->io_oled.o_data; |
zip->dma.len= 6144; |
zip->dma.ctrl = DMAONEATATIME|DMA_CONSTDST|DMA_OLED; |
// timer_delay(256); |
// zip_halt(); |
#else |
for(int i=0; i<6144; i++) { |
while(sys->io_oled.o_ctrl & OLED_BUSY) |
; |
sys->io_oled.o_data = img[i]; |
} |
#endif |
} |
|
/* |
* entry() |
266,7 → 291,7
* |
* In all (current) ZipCPU programs, the programs start with an entry() |
* function that takes no arguments. The actual bootup entry can be found |
* in the bootstram directory, but that calls us here. |
* in the bootstrap.c file, but that calls us here. |
* |
*/ |
void entry(void) { |
375,11 → 400,8
sys->io_oled.o_ctrl = 0x2075003f; // Sets row min/max address |
|
// Now ... finally ... we can send our image. |
for(int i=0; i<6144; i++) { |
while(sys->io_oled.o_ctrl & OLED_BUSY) |
; |
sys->io_oled.o_data = splash[i]; |
} |
oled_show_image(splash); |
wait_on_interrupt(SYSINT_DMAC); |
|
// Wait 25 seconds. The LEDs are for a fun effect. |
sys->io_ledctrl = 0x0f1; |
396,11 → 418,8
|
// Display a second image. |
sys->io_ledctrl = 0x0fc; |
for(int i=0; i<6144; i++) { |
while(sys->io_oled.o_ctrl & OLED_BUSY) |
; |
sys->io_oled.o_data = mug[i]; |
} |
oled_show_image(mug); |
wait_on_interrupt(SYSINT_DMAC); |
|
// Leave this one in effect for 5 seconds only. |
sys->io_ledctrl = 0x0f8; |
/board/zipsys.h
48,8 → 48,15
volatile int *rd, *wr; |
} ZIPDMA; |
|
#define DMA_TRIGGER 0x00008000 |
#define DMACLEAR 0xffed0000 |
#define DMACCOPY 0x0fed0000 |
#define DMACERR 0x40000000 |
#define DMA_CONSTSRC 0x20000000 |
#define DMA_CONSTDST 0x10000000 |
#define DMAONEATATIME 0x0fed0001 |
#define DMA_BUSY 0x80000000 |
#define DMA_ERR 0x40000000 |
|
typedef struct { |
volatile int pic, wdt, err, apic, tma, tmb, tmc, |
66,22 → 73,28
#define SYSINT_TMB 0x0008 |
#define SYSINT_TMA 0x0010 |
#define SYSINT_AUX 0x0020 |
#define SYSINT_BRD 0x0040 |
// |
#define SYSINT_CK 0x0080 |
#define SYSINT_FLASH 0x0100 |
#define SYSINT_SCOP 0x0200 |
#define SYSINT_GPIO 0x0400 |
#define SYSINT_PWM 0x0800 |
#define SYSINT_UARTRX 0x1000 |
#define SYSINT_UARTTX 0x2000 |
#define SYSINT_SDCARD 0x4000 |
#define SYSINT_PPS 0x0040 |
#define SYSINT_NETRX 0x0080 |
#define SYSINT_NETTX 0x0100 |
#define SYSINT_UARTRX 0x0200 |
#define SYSINT_UARTTX 0x0400 |
#define SYSINT_GPSRX 0x0800 |
#define SYSINT_GPSTX 0x1000 |
#define SYSINT_SDCARD 0x2000 |
#define SYSINT_OLED 0x4000 |
|
|
#define ALTINT_UIC 0x001 |
#define ALTINT_UTC 0x008 |
#define ALTINT_MIC 0x010 |
#define ALTINT_MTC 0x080 |
#define ALTINT_UIC 0x0001 |
#define ALTINT_UTC 0x0008 |
#define ALTINT_MIC 0x0010 |
#define ALTINT_MTC 0x0080 |
#define ALTINT_RTC 0x0100 |
#define ALTINT_BTN 0x0200 |
#define ALTINT_SWITCH 0x0400 |
#define ALTINT_FLASH 0x0800 |
#define ALTINT_SCOPE 0x1000 |
#define ALTINT_GPIO 0x2000 |
|
|
#define CC_Z 0x0001 |
98,6 → 111,9
#define CC_DIVERR 0x0800 |
#define CC_FPUERR 0x1000 |
#define CC_IPHASE 0x2000 |
#define CC_MMUERR 0x8000 |
#define CC_EXCEPTION (CC_ILL|CC_BUSERR|CC_DIVERR|CC_FPUERR|CC_MMUERR) |
#define CC_FAULT (CC_ILL|CC_BUSERR|CC_DIVERR|CC_FPUERR) |
|
// extern void zip_break(void); |
extern void zip_rtu(void); |
121,8 → 137,9
#endif |
|
#define EINT(A) (0x80000000|(A<<16)) |
#define DINT(A) (0x80000000|(A<<16)) |
#define DINT(A) (0x00000000|(A<<16)) |
#define CLEARPIC 0x7fff7fff |
#define DALLPIC 0x7fff0000 // Disable all PIC interrupt sources |
|
static ZIPSYS *const zip = (ZIPSYS *)(ZIPSYS_ADDR); |
|
/host/zipstate.cpp
70,7 → 70,7
printf("ERR: errcount(%d) >= MAXERR on cmd_read(a=%02x)\n", |
errcount, r); |
printf("ZIPCTRL = 0x%08x", s); |
if ((s & 0x0200)==0) printf(" STALL"); |
if ((s & 0x0200)==0) printf(" BUSY"); |
if (s & 0x0400) printf(" HALTED"); |
if ((s & 0x03000)==0x01000) |
printf(" SW-HALT"); |
109,7 → 109,7
printf("0x%08x: ", v); |
if (v & 0x0080) printf("PINT "); |
// if (v & 0x0100) printf("STEP "); // self resetting |
if((v & 0x00200)==0) printf("STALL "); |
if((v & 0x00200)==0) printf("BUSY "); |
if (v & 0x00400) printf("HALTED "); |
if((v & 0x03000)==0x01000) { |
printf("SW-HALT"); |