Index: tools/xml2h.py =================================================================== --- tools/xml2h.py (revision 0) +++ tools/xml2h.py (revision 0) @@ -0,0 +1,175 @@ +#!/usr/bin/python +import sys, os.path, array, re +from xml.dom import Node +from xml.dom.minidom import parse + + +C_IDENT_RE = re.compile('^[0-9a-zA-Z_]+$') + + +def getText(nodelist): + rc = "" + for node in nodelist: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + + +def descendAll(root, tagname): + for child in root.childNodes: + if child.nodeType == Node.ELEMENT_NODE and child.tagName == tagname: + yield child + + +def descend(root, tagname): + return descendAll(root, tagname).next() + + +def getTagText(root, tagname): + try: + tag = descend(root, tagname) + except StopIteration: + return None + return getText(tag.childNodes) + + +def main(): + dom = parse(sys.stdin) + + ofd = descend(dom, "ofd") + object_file = descend(ofd, "object_file") + object_file_name = descend(object_file, "name") + + out_filepath = getText(object_file_name.childNodes) + sys.stderr.write("*.out filename (input): %s\n" % out_filepath) + + out_file = open(out_filepath, "rb") + h_file = sys.stdout + + h_file.write("""#ifndef DSP_IMAGE +#define DSP_IMAGE +/* + * Automatically generated by xml2h.py from %s. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +""" % out_filepath) + + # Section data and directory. + h_directory = [""" +static const struct dsp_section dsp_image[] = {"""] + + ti_coff = descend(object_file, "ti_coff") + for section in descendAll(ti_coff, "section"): + page = int(getTagText(section, "page") or "0", 16) + name = getTagText(section, "name") + physical_addr = int(getTagText(section, "physical_addr"), 16) + raw_data_size = int(getTagText(section, "raw_data_size"), 16) + copy = getTagText(section, "copy") + data = getTagText(section, "data") + regular = getTagText(section, "regular") + text = getTagText(section, "text") + bss = getTagText(section, "bss") + + file_offsets = descend(section, "file_offsets") + raw_data_ptr = int(getTagText(file_offsets, "raw_data_ptr"), 16) + + if copy: + # Empirically, .debug* sections have this attribute set. + sys.stderr.write( + "%s: didn't copy debug section ('copy' attribute set)\n" % + name) + continue + + if raw_data_size == 0: + sys.stderr.write("%s: not copying empty section\n" % name) + continue + + if raw_data_size % 2 != 0: + sys.stderr.write("%s: error, raw_data_size 0x%04x not a multiple " + "of word size (2 bytes)\n" % (name, raw_data_size)) + break + + if data or regular or text: + sys.stderr.write("%s: placing 0x%04x words at 0x%04x from offset " + "0x%08x\n" % ( + name, raw_data_size >> 1, physical_addr, raw_data_ptr)) + + sanitized_name = name.replace(".", "_") + h_file.write(("static const unsigned short _section%s[] = {\n" % + sanitized_name)) + + out_file.seek(raw_data_ptr) + data = array.array('H') + data.fromfile(out_file, raw_data_size >> 1) + h_file.write("\t") + for word in data: + h_file.write("0x%04x, " % word) + h_file.write(""" +}; +""") + + h_directory.append("\t{_section%s, 0x%04x, 0x%04x}," % ( + sanitized_name, physical_addr, raw_data_size >> 1)) + + continue + + if bss: + sys.stderr.write("%s: bss section, 0x%04x words at 0x%04x\n" % ( + name, raw_data_size >> 1, physical_addr)) + + h_directory.append("\t{NULL /* %s */, 0x%04x, 0x%04x}," % ( + name, physical_addr, raw_data_size >> 1)) + continue + + sys.stderr.write("%s: error, unprocessed section\n" % name) + + h_file.write("\n") + + h_directory.append("\t{NULL, 0, 0}") + h_directory.append("};") + + h_file.write("\n".join(h_directory)) + h_file.write("\n") + + # Symbols. + symbol_table = descend(ti_coff, "symbol_table") + h_file.write(""" +/* Symbol table, usable with the DSP_() macro (see dsp-target.h). */ +""") + for symbol in descendAll(symbol_table, "symbol"): + name = getTagText(symbol, "name") + kind = getTagText(symbol, "kind") + value = int(getTagText(symbol, "value"), 16) + + if kind != "defined": + continue + + if not C_IDENT_RE.match(name): + continue + + h_file.write("#define %s 0x%04x\n" % (name, value)) + + h_file.write("\n#endif\n") + h_file.close() + out_file.close() + + dom.unlink() + + +if __name__ == "__main__": + main() Index: tools/configure =================================================================== --- tools/configure (revision 15801) +++ tools/configure (working copy) @@ -1942,7 +1942,7 @@ manual *.pdf *.a credits.raw @OUTPUT@ bitmaps pluginbitmaps \ @ARCHOSROM@ @FLASHFILE@ UI256.bmp rockbox-full.zip \ html txt rockbox-manual*.zip sysfont.h rockbox-info.txt \ - voicefontids *.wav *.mp3 *.voice + voicefontids *.wav *.mp3 *.voice dsp-image.h tools: \$(SILENT)\$(MAKE) -C \$(TOOLSDIR) CC=\$(HOSTCC) AR=\$(HOSTAR) @TOOLSET@ Index: bootloader/mrobe500.c =================================================================== --- bootloader/mrobe500.c (revision 15801) +++ bootloader/mrobe500.c (working copy) @@ -1,257 +1,49 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: $ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - +#include "stdlib.h" #include "inttypes.h" #include "string.h" +#include "debug.h" #include "cpu.h" #include "system.h" -#include "lcd.h" -#include "kernel.h" -#include "thread.h" +#include "dsp-target.h" +#include "spi-target.h" +#include "tsc2100.h" #include "ata.h" -#include "fat.h" #include "disk.h" -#include "font.h" -#include "adc.h" -#include "backlight.h" -#include "backlight-target.h" -#include "button.h" -#include "panic.h" #include "power.h" -#include "file.h" -#include "common.h" -#include "rbunicode.h" -#include "usb.h" -#include "spi.h" -#include "uart-target.h" -#include "tsc2100.h" -#include "time.h" -#include "system-arm.h" +#include "../target/arm/tms320dm320/dsp/ipc.h" -#define MRDEBUG +void breakpoint(void); -#if defined(MRDEBUG) - -extern int line; -#if 0 -struct touch_calibration_point tl, br; - -void touchpad_get_one_point(struct touch_calibration_point *p) -{ - int data = 0; - int start = current_tick; - while (TIME_AFTER(start+(HZ/3), current_tick)) - { - if (button_read_device()&BUTTON_TOUCHPAD) - { - data = button_get_last_touch(); - p->val_x = data>>16; - p->val_y = data&0xffff; - start = current_tick; - } - else if (data == 0) - start = current_tick; - } -} - -#define MARGIN 25 -#define LEN 7 -void touchpad_calibrate_screen(void) -{ - reset_screen(); - printf("touch the center of the crosshairs to calibrate"); - /* get the topleft value */ - lcd_hline(MARGIN-LEN, MARGIN+LEN, MARGIN); - lcd_vline(MARGIN, MARGIN-LEN, MARGIN+LEN); - lcd_update(); - tl.px_x = MARGIN; tl.px_y = MARGIN; - touchpad_get_one_point(&tl); - reset_screen(); - printf("touch the center of the crosshairs to calibrate"); - /* get the topright value */ - lcd_hline(LCD_WIDTH-MARGIN-LEN, LCD_WIDTH-MARGIN+LEN, LCD_HEIGHT-MARGIN); - lcd_vline(LCD_WIDTH-MARGIN, LCD_HEIGHT-MARGIN-LEN, LCD_HEIGHT-MARGIN+LEN); - lcd_update(); - br.px_x = LCD_WIDTH-MARGIN; br.px_y = LCD_HEIGHT-MARGIN; - touchpad_get_one_point(&br); - reset_screen(); - line++; - printf("tl %d %d", tl.val_x, tl.val_y); - printf("br %d %d", br.val_x, br.val_y); - line++; - set_calibration_points(&tl, &br); -} -#endif -static uint8_t bl_command[] = {0xa4, 0x00, 0x00, 0xbb}; -int brightness = 0; - -void mrdebug(void) -{ - int button=0; -#if 0 - use_calibration(false); - touchpad_calibrate_screen(); - use_calibration(true); -#endif - - while(true) - { -#if 0 - struct tm *t = get_time(); - printf("%d:%d:%d %d %d %d", t->tm_hour, t->tm_min, t->tm_sec, t->tm_mday, t->tm_mon, t->tm_year); - printf("time: %d", mktime(t)); -#endif - button = button_get(false); - if (button == BUTTON_POWER) - { - printf("reset"); - IO_GIO_BITSET1|=1<<10; - } - if (button==BUTTON_RC_VOL_DOWN) - { - brightness = (brightness - 5) & 0x7f; - bl_command[2] = brightness; - spi_block_transfer(SPI_target_BACKLIGHT, bl_command, 4, 0, 0); - } - else if (button==BUTTON_RC_VOL_UP) - { - brightness = (brightness + 5) & 0x7f; - bl_command[2] = brightness; - spi_block_transfer(SPI_target_BACKLIGHT, bl_command, 4, 0, 0); - } -// { -// short x,y,z1,z2; -// tsc2100_read_values(&x, &y, &z1, &z2); -// printf("x: %04x y: %04x z1: %04x z2: %04x", x, y, z1, z2); -// printf("tsadc: %4x", tsc2100_readreg(TSADC_PAGE, TSADC_ADDRESS)&0xffff); -// // tsc2100_keyclick(); /* doesnt work :( */ -// line -= 6; -// } -#if 1 - if (button&BUTTON_TOUCHPAD) - { - if (button&BUTTON_REL) - continue; - unsigned int data = button_get_data(); - int x = (data&0xffff0000)>>16, y = data&0x0000ffff; - reset_screen(); - line = 9; - printf("%x %d %d\n", button, x,y); - lcd_hline(x-5, x+5, y); - lcd_vline(x, y-5, y+5); - lcd_update(); - } -#endif - } -} -#endif - -void main(void) -{ - unsigned char* loadbuffer; - int buffer_size; +void main(void) { + unsigned int i; int rc; - int(*kernel_entry)(void); + DEBUGF("initing..."); power_init(); - lcd_init(); system_init(); kernel_init(); - - set_irq_level(0); - set_fiq_status(FIQ_ENABLED); - - adc_init(); - button_init(); - backlight_init(); - - font_init(); - - lcd_setfont(FONT_SYSFIXED); - - /* Show debug messages if button is pressed */ -// if(button_read_device()) - verbose = true; - - printf("Rockbox boot loader"); - printf("Version %s", APPSVERSION); - - usb_init(); - - /* Enter USB mode without USB thread */ - if(usb_detect()) - { - const char msg[] = "Bootloader USB mode"; - reset_screen(); - lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, - (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); - lcd_update(); - - ide_power_enable(true); - ata_enable(false); - sleep(HZ/20); - usb_enable(true); - - while (usb_detect()) - { - ata_spin(); /* Prevent the drive from spinning down */ - sleep(HZ); - } - - usb_enable(false); - - reset_screen(); - lcd_update(); - } -#if defined(MRDEBUG) - mrdebug(); -#endif - printf("ATA"); + /*spi_init();*/ + set_irq_level(IRQ_ENABLED); rc = ata_init(); - if(rc) - { - reset_screen(); - error(EATA, rc); - } - - printf("disk"); - disk_init(); - - printf("mount"); + DEBUGF("ata_init: rc=%d", rc); + rc = disk_init(); + DEBUGF("disk_init: rc=%d", rc); rc = disk_mount_all(); - if (rc<=0) - { - error(EDISK,rc); - } + DEBUGF("disk_mount_all: rc=%d", rc); - printf("Loading firmware"); + dsp_init(); - loadbuffer = (unsigned char*) 0x00900000; - buffer_size = (unsigned char*)0x01900000 - loadbuffer; + tsc2100_writereg(TSDACGAIN_PAGE, TSDACGAIN_ADDRESS, 0x2020/*x0303*/); - rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); - if(rc < 0) - error(EBOOTFILE, rc); - - if (rc == EOK) - { - kernel_entry = (void*) loadbuffer; - rc = kernel_entry(); - } + /* audio control: 1=0300 2=44FC cpc=3B80 3=2803 4=0022 5=FE00 + + 1=left justified + 3=44.1khz, continous xfer, master + */ + + DEBUGF("waking DSP (user reset vector)..."); + dsp_wake(); + + for (;;) asm("mcr p15, 0, r0, c7, c0, 4"); + breakpoint(); } Index: firmware/debug.c =================================================================== --- firmware/debug.c (revision 15801) +++ firmware/debug.c (working copy) @@ -229,6 +229,70 @@ } #endif /* HAVE_GDB_API */ + +#ifdef CPU_ARM +void breakpoint(void) +{ + asm("bkpt 0"); +} + +/* Borrowed from linux-2.6.22.6/arch/arm/kernel/debug.S */ +static void senduart(unsigned long ch) { + __asm__(" mov r4, #0x2000000\n\t" + "1001:\n\t" + " subs r4, r4, #1\n\t" + " bmi 1002f\n\t" + " mrc p14, 0, r5, c0, c0, 0\n\t" + " tst r5, #2\n\t" + " bne 1001b\n\t" + "1002:\n\t" : : : "cc", "r4", "r5"); + __asm__("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch)); +} + +/* openocd protocol, see openocd/src/target_request.c */ +typedef enum target_req_cmd +{ + TARGET_REQ_TRACEMSG, + TARGET_REQ_DEBUGMSG, +/* TARGET_REQ_SEMIHOSTING, */ +} target_req_cmd_t; + +void trace_point(int number) { + senduart((number << 8) | TARGET_REQ_TRACEMSG); +} + +void hexmsg(const unsigned char *data, int size, uint32_t length) { + uint32_t word; + + senduart((length << 16) | (size << 8) | TARGET_REQ_DEBUGMSG); + + while (length >= 4) { + senduart(*(uint32_t *)data); + data += 4; + length -= 4; + } + + word = 0; + switch (length) { + case 3: word |= data[2] << 16; + case 2: word |= data[1] << 8; + case 1: word |= data[0]; + senduart(word); + case 0: + ; + } +} + +static void asciimsg(const char *msg) { + hexmsg((const unsigned char *)msg, 0, strlen(msg)); +} + +static void debug(const char *msg) +{ + asciimsg(msg); +} + +#endif #endif /* end of DEBUG section */ #ifdef __GNUC__ @@ -236,12 +300,15 @@ #endif { #ifdef DEBUG + /* Protect the (static) buffer from concurrent modification. */ + int old_level = set_irq_level(IRQ_DISABLED); va_list ap; va_start(ap, fmt); vsnprintf(debugmembuf, sizeof(debugmembuf), fmt, ap); va_end(ap); debug(debugmembuf); + set_irq_level(old_level); #else (void)fmt; #endif Index: firmware/Makefile =================================================================== --- firmware/Makefile (revision 15801) +++ firmware/Makefile (working copy) @@ -24,7 +24,7 @@ all: $(OUTPUT) $(EXTRA_TARGETS) -$(DEPFILE): $(BUILDDIR)/sysfont.h +$(DEPFILE): $(BUILDDIR)/sysfont.h $(BUILDDIR)/dsp-image.h dep: $(DEPFILE) @@ -49,4 +49,7 @@ $(call PRINTS,CONVBDF)$(TOOLSDIR)/convbdf -c -o $(OBJDIR)/sysfont.c $< $(call PRINTS,CC sysfont.c)$(CC) $(CFLAGS) -c $(OBJDIR)/sysfont.c -o $@ +$(BUILDDIR)/dsp-image.h: target/arm/tms320dm320/dsp/arm.c target/arm/tms320dm320/dsp/arm.h target/arm/tms320dm320/dsp/ipc.h target/arm/tms320dm320/dsp/main.c target/arm/tms320dm320/dsp/registers.h target/arm/tms320dm320/dsp/vectors.asm target/arm/tms320dm320/dsp/linker.cmd + $(call PRINTS,MAKE in target/arm/tms320dm320/dsp)$(MAKE) -C target/arm/tms320dm320/dsp OBJDIR=$(OBJDIR)/target/arm/tms320dm320/dsp + -include $(DEPFILE) Index: firmware/target/arm/tms320dm320/dsp/arm.c =================================================================== --- firmware/target/arm/tms320dm320/dsp/arm.c (revision 0) +++ firmware/target/arm/tms320dm320/dsp/arm.c (revision 0) @@ -0,0 +1,30 @@ +#include +#include "arm.h" +#include "registers.h" +#include "ipc.h" + +volatile struct ipc_message status; + +volatile int acked; +interrupt void handle_int0(void) { + IFR = 1; + acked = 1; +} + +void debugf(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + status.msg = MSG_DEBUGF; + vsnprintf((char *)status.payload.debugf.buffer, sizeof(status), fmt, args); + va_end(args); + + /* Wait until ARM has picked up data. */ + acked = 0; + int_arm(); + while (!acked) { + /* IDLE alone never seems to wake up :( */ + asm(" IDLE 1"); + asm(" NOP"); + } + acked = 2; +} Index: firmware/target/arm/tms320dm320/dsp/vectors.asm =================================================================== --- firmware/target/arm/tms320dm320/dsp/vectors.asm (revision 0) +++ firmware/target/arm/tms320dm320/dsp/vectors.asm (revision 0) @@ -0,0 +1,143 @@ +;* Copyright (c) 2007, C.P.R. Baaij +;* All rights reserved. +;* +;* Redistribution and use in source and binary forms, with or without +;* modification, are permitted provided that the following conditions are met: +;* * Redistributions of source code must retain the above copyright +;* notice, this list of conditions and the following disclaimer. +;* * Redistributions in binary form must reproduce the above copyright +;* notice, this list of conditions and the following disclaimer in the +;* documentation and/or other materials provided with the distribution. +;* +;* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +;* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +;* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +;* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +;* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +;* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +;* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;*-----------------------------------------------------------------------------* +;* Interrupt Vectors * +;*-----------------------------------------------------------------------------* + .mmregs + + ; External Functions + .global _handle_int0 + .global _c_int00 + .global _handle_dma0 + .global _handle_dmac + + .sect ".vectors" +; Reset Interrupt +RS_V: BD _c_int00 + NOP + NOP + +; Non-Maskable Interrupt +NMI_V: RETE + NOP + NOP + NOP + +; Software Interrupts +SINt17_V: .space 4*16 +SINt18_V: .space 4*16 +SINt19_V: .space 4*16 +SINt20_V: .space 4*16 +SINt21_V: .space 4*16 +SINt22_V: .space 4*16 +SINt23_V: .space 4*16 +SINt24_V: .space 4*16 +SINt25_V: .space 4*16 +SINt26_V: .space 4*16 +SINt27_V: .space 4*16 +SINt28_V: .space 4*16 +SINt29_V: .space 4*16 +SINt30_V: .space 4*16 +; INT0 - ARM Interrupting DSP via HPIB +INT0_V: BD _handle_int0 + NOP + NOP +; INT1 - Interrupt is generated based on the settings of DSP_SYNC_STATE and +; DSP_SYNC_MASK register of the coprocessor subsystem or when DSPINT1 bit in +; CP_INTC is set. +INT1_V: RETE + NOP + NOP + NOP +; INT2 - Interrupt is generated when DSPINT2 bit in CP_INTC register of the +; coprocessor subsystem is set. +INT2_V: RETE + NOP + NOP + NOP +; Timer Interrupt +TINT_V: RETE + NOP + NOP + NOP +; McBSP0 receive interrupt +BRINT0_V: RETE + NOP + NOP + NOP +; McBSP0 transmit interrupt +BXINT0_V: RETE + NOP + NOP + NOP +; DMA Channel-0 interrupt +DMAC0_V: BD _handle_dma0 + NOP + NOP +; DMA Channel-1 interrupt +DMAC1_V: RETE + NOP + NOP + NOP +; INT3 - Interrupt is generated when DSPINT3 bit in CP_INTC register of the +; coprocessor subsystem is set or on write of any value to BRKPT_TRG +INT3_V: RETE + NOP + NOP + NOP +; HPIB HINT to DSP +HINT_V: RETE + NOP + NOP + NOP +; BRINT1/DMAC2 McBSP1 receive interrupt +BRINT1_V: RETE + NOP + NOP + NOP +; BXINT1/DMAC3 McBSP1 transmit interrupt +BXINT1_V: RETE + NOP + NOP + NOP +; DMA Channel-4 interrupt +DMAC4_V: RETE + NOP + NOP + NOP +; DMA Channel-5 interrupt +DMAC5_V: RETE + NOP + NOP + NOP +; HPIB DMAC interrupt +HPIB_DMA_V: BD _handle_dmac + NOP + NOP + +; EHIF interrupt to DSP +EHIV_V: RETE + NOP + NOP + NOP + .end Index: firmware/target/arm/tms320dm320/dsp/main.c =================================================================== --- firmware/target/arm/tms320dm320/dsp/main.c (revision 0) +++ firmware/target/arm/tms320dm320/dsp/main.c (revision 0) @@ -0,0 +1,162 @@ +#include "registers.h" +#include "arm.h" +#include "ipc.h" +#include + +/* This is placed at the right (aligned) address using linker.cmd. */ +#pragma DATA_SECTION (data, ".dma") +signed short data[PCM_SIZE / 2]; + +/* Filled in by loader. */ +unsigned short sdem_addrh; +unsigned short sdem_addrl; + +interrupt void handle_dma0(void) { + unsigned long sdem_addr; + /* Byte offset to half-buffer locked by DMA0. + 0 for top, PCM_SIZE/2(0x4000) for bottom */ + unsigned short dma0_locked; + unsigned short dma0_unlocked; + + IFR = 1 << 6; + + /* DMSRC0 is the beginning of the DMA0-locked SARAM half-buffer. */ + DMSA = 0x00 /* DMSRC0 */; + dma0_locked = (DMSDN << 1) & (PCM_SIZE / 2); + dma0_unlocked = dma0_locked ^ (PCM_SIZE / 2); + + /* ARM, decode into same half, in SDRAM. */ + status.msg = MSG_REFILL; + status.payload.refill.topbottom = dma0_locked; + int_arm(); + + /* DMAC, copy opposite halves from SDRAM to SARAM. */ + sdem_addr = ((unsigned long)sdem_addrh << 16 | sdem_addrl) + dma0_unlocked; + SDEM_ADDRL = sdem_addr & 0xffff; + SDEM_ADDRH = sdem_addr >> 16; + DSP_ADDRL = (unsigned short)data + (dma0_unlocked >> 1); + DSP_ADDRH = 0; + DMA_SIZE = PCM_SIZE / 2; + DMA_CTRL = 0; + + status.payload.refill._DMA_TRG = DMA_TRG; + status.payload.refill._SDEM_ADDRH = SDEM_ADDRH; + status.payload.refill._SDEM_ADDRL = SDEM_ADDRL; + status.payload.refill._DSP_ADDRH = DSP_ADDRH; + status.payload.refill._DSP_ADDRL = DSP_ADDRL; + + DMA_TRG = 1; +} + +interrupt void handle_dmac(void) { + IFR = 1 << 11; +} + +void main(void) { + register int i; + + TCR = 1 << 4; /* Stop the timer. */ + IMR = 0xffff; /* Unmask all interrupts. */ + IFR = IFR; /* Clear all pending interrupts. */ + asm(" rsbx INTM"); /* Globally enable interrupts. */ + + /* Configure McBSP */ + SPCR10 = 0; /* Receiver reset */ + SPCR20 = 3 << 4; /* Rate gen disabled, RINT=XSYNCERR, TX disabled for now */ + PCR0 = 1 << 1; /* Serial port pins, external frame sync, external clock, + frame sync FSX is active-high, + TX data sampled on falling clock */ + XCR10 = 0x00a0; /* 1 word per frame, 32 bits per word */ + XCR20 = 0; /* Single-phase, unexpected frame pulse restarts xfer, + 0-bit data delay */ + + /* Configure DMA */ + DMSFC0 = 2 << 12 | 1 << 11; /* Event XEVT0, 32-bit transfers, 0 frame count */ + DMMCR0 = 1 << 14 | 1 << 13 | /* Interrupts generated, Half and full buffer */ + 1 << 12 | 1 << 8 | 1 << 6 | 1; /* ABU mode, + From data space with postincrement, + To data space with no mod */ + DMSRC0 = (unsigned short)&data; + DMDST0 = (unsigned short)&DXR20; /* First of two-word register pair */ + DMCTR0 = sizeof(data); + + /* Run, Rudolf, run! (with DMA0 interrupts) */ + DMPREC = 2 << 6 | 1; + + /* Trigger first XEVT0 */ + SPCR20 |= 1; + + for (;;) { + asm(" IDLE 1"); + } +} + +/* Obsoleted/testing snippets: */ +#ifdef REMAP_VECTORS + /* Remap vectors to 0x3F80 (set in linker.cmd). */ + PMST = (PMST & 0x7f) | 0x3F80; + + /* Make sure working interrupts aren't a fluke. */ + memset((unsigned short *)0x7f80, 0, 0x80); +#endif + +#ifdef DATA_32_SINE + for (i = 0; i < 32; i++) { + double ratio = ((double)i)/32.0; + double rad = 3.0*3.141592*ratio; + double normal = sin(rad); + double scaled = 32767.0*(normal); + data[2*i + 0] = -(signed short)scaled; + data[2*i + 1] = (signed short)scaled; + } +#endif + +#ifdef MANUAL_TRANSFER + register signed short *p; + + debugf("starting write"); + + i = 0; + p = data; + SPSA0 = 0x01; + for (;;) { + while ((SPSD0 & (1 << 1)) == 0); + DXR20 = *p++; // left channel + DXR10 = *p++; // right channel + if (++i == 32) { + p = data; + i = 0; + } + } +#endif + +#ifdef INIT_MSG + /* Copy codec init data (before debugf, which clobbers status). */ + if (status.msg != MSG_INIT) { + debugf("No init message (%04x: %04x %04x %04x %04x instead)", + (unsigned short)&status, + ((unsigned short *)&status)[0], + ((unsigned short *)&status)[1], + ((unsigned short *)&status)[2], + ((unsigned short *)&status)[3]); + return; + } + + memcpy(&init, (void *)&status.payload.init, sizeof(init)); +#endif + +#ifdef IPC_SIZES + debugf("sizeof(ipc_message)=%uw offset(ipc_message.payload)=%uw", + sizeof(struct ipc_message), (int)&((struct ipc_message*)0)->payload); +#endif + +#ifdef VERBOSE_INIT + debugf("codec started with PCM at SDRAM offset %04x:%04x", + sdem_addrh, sdem_addrl); +#endif + +#ifdef SPIKE_DATA + for (i = 0; i < 0x2000; i++) { + data[2*i ] = data[2*i+1] = ((i % 32) == 0) * 32767; + } +#endif Index: firmware/target/arm/tms320dm320/dsp/arm.h =================================================================== --- firmware/target/arm/tms320dm320/dsp/arm.h (revision 0) +++ firmware/target/arm/tms320dm320/dsp/arm.h (revision 0) @@ -0,0 +1,13 @@ +#ifndef ARM_H +#define ARM_H +#include "registers.h" + +extern volatile struct ipc_message status; + +void debugf(const char *fmt, ...); + +inline void int_arm(void) { + CP_INTC = 1 << 3; +} + +#endif Index: firmware/target/arm/tms320dm320/dsp/linker.cmd =================================================================== --- firmware/target/arm/tms320dm320/dsp/linker.cmd (revision 0) +++ firmware/target/arm/tms320dm320/dsp/linker.cmd (revision 0) @@ -0,0 +1,29 @@ +-c +-x +-stack 0x1000 +-heap 0x100 +-l rts500.lib + +MEMORY +{ +PAGE 0: + DARAM: origin = 80h, length = 7F80h + SARAM: origin = 8000h, length = 4000h +} + +SECTIONS +{ + .text PAGE 0 + .cinit PAGE 0 + .switch PAGE 0 + + .bss PAGE 0 + .const PAGE 0 + .sysmem PAGE 0 + .stack PAGE 0 + + .vectors : PAGE 0 load = 7F80h + + /* DMA buffers for ABU mode must start on a 2*size boundary. */ + .dma : PAGE 0 load = 0x8000 +} Index: firmware/target/arm/tms320dm320/dsp/Makefile =================================================================== --- firmware/target/arm/tms320dm320/dsp/Makefile (revision 0) +++ firmware/target/arm/tms320dm320/dsp/Makefile (revision 0) @@ -0,0 +1,39 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id: Makefile 12058 2007-01-18 00:46:52Z dave $ +# + +# http://daniel.haxx.se/blog/2007/11/18/free-to-use-compiler-from-ti/ +CC = cl500 +LD = lnk500 +CFLAGS = $(BUILDDATE) +# There's more in linker.cmd. +LDFLAGS = -w + +OBJS = arm.obj main.obj vectors.obj +OBJS := $(patsubst %.obj, $(OBJDIR)/%.obj, $(OBJS)) + +all: $(BUILDDIR)/dsp-image.h + +$(BUILDDIR)/dsp-image.h: $(OBJS) linker.cmd + $(call PRINTS,LNK500 dsp-image.out)lnk500 $(LDFLAGS) -o $(OBJDIR)/dsp-image.out $^ + $(call PRINTS,OFD500+XML2H $(@F))ofd500 -x -o /dev/stdout $(OBJDIR)/dsp-image.out | python $(TOOLSDIR)/xml2h.py $(OBJDIR)/dsp-image.xml > $@ + +$(OBJDIR)/%.obj: %.asm + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CL500 $<)$(CC) $(CFLAGS) -fr $(dir $@) $< + +$(OBJDIR)/%.obj: %.c + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CL500 $<)$(CC) $(CFLAGS) -fr $(dir $@) $< + +$(OBJDIR)/arm.obj: arm.c arm.h registers.h ipc.h + +$(OBJDIR)/main.obj: main.c arm.h registers.h ipc.h + +# For PRINTS. +include $(TOOLSDIR)/make.inc Index: firmware/target/arm/tms320dm320/dsp/registers.h =================================================================== --- firmware/target/arm/tms320dm320/dsp/registers.h (revision 0) +++ firmware/target/arm/tms320dm320/dsp/registers.h (revision 0) @@ -0,0 +1,70 @@ +#ifndef REGISTERS_H +#define REGISTERS_H + +#define C5409_REG(addr) (*(volatile unsigned short *)(addr)) + +/* This is NOT good for reading, only for writing. */ +#define BANKED_REG(spsa, spsd, subaddr) spsa = (subaddr), spsd + +#define IMR C5409_REG(0x00) +#define IFR C5409_REG(0x01) + +#define PMST C5409_REG(0x1D) + +#define TCR C5409_REG(0x26) + +/* McBSP 0 (SPRU302 Chapter 2) */ +#define DXR20 C5409_REG(0x22) +#define DXR10 C5409_REG(0x23) +#define SPSA0 C5409_REG(0x38) +#define SPSD0 C5409_REG(0x39) +#define SPCR10 BANKED_REG(SPSA0, SPSD0, 0x00) +#define SPCR20 BANKED_REG(SPSA0, SPSD0, 0x01) +#define XCR10 BANKED_REG(SPSA0, SPSD0, 0x04) +#define XCR20 BANKED_REG(SPSA0, SPSD0, 0x05) +#define PCR0 BANKED_REG(SPSA0, SPSD0, 0x0e) + +/* McBSP 1 */ +#define DXR21 C5409_REG(0x42) +#define DXR11 C5409_REG(0x43) +#define SPSA1 C5409_REG(0x48) +#define SPSD1 C5409_REG(0x49) +#define SPCR11 BANKED_REG(SPSA1, SPSD1, 0x00) +#define SPCR21 BANKED_REG(SPSA1, SPSD1, 0x01) +#define XCR11 BANKED_REG(SPSA1, SPSD1, 0x04) +#define XCR21 BANKED_REG(SPSA1, SPSD1, 0x05) +#define PCR1 BANKED_REG(SPSA1, SPSD1, 0x0e) + +/* DMA */ +#define DMPREC C5409_REG(0x54) +#define DMSA C5409_REG(0x55) +#define DMSDI C5409_REG(0x56) +#define DMSDN C5409_REG(0x57) +#define DMSRC0 BANKED_REG(DMSA, DMSDN, 0x00) +#define DMDST0 BANKED_REG(DMSA, DMSDN, 0x01) +#define DMCTR0 BANKED_REG(DMSA, DMSDN, 0x02) +#define DMSFC0 BANKED_REG(DMSA, DMSDN, 0x03) +#define DMMCR0 BANKED_REG(DMSA, DMSDN, 0x04) + + +/* DM320 */ +ioport unsigned short port280; +#define CP_INTC port280 +ioport unsigned short port8000; +#define SDEM_ADDRL port8000 +ioport unsigned short port8001; +#define SDEM_ADDRH port8001 +ioport unsigned short port8002; +#define DSP_ADDRL port8002 +ioport unsigned short port8003; +#define DSP_ADDRH port8003 +ioport unsigned short port8004; +#define DMA_SIZE port8004 +ioport unsigned short port8005; +#define DMA_CTRL port8005 +ioport unsigned short port8006; +#define DMA_TRG port8006 +ioport unsigned short port8007; +#define DMA_REST port8007 + +#endif Index: firmware/target/arm/tms320dm320/dsp-dm320.c =================================================================== --- firmware/target/arm/tms320dm320/dsp-dm320.c (revision 15801) +++ firmware/target/arm/tms320dm320/dsp-dm320.c (working copy) @@ -22,6 +22,8 @@ #include "debug.h" #include "string.h" #include "dsp-target.h" +#include "dsp/ipc.h" +#include "file.h" /* A "DSP image" is an array of these, terminated by raw_data_size_half = 0. */ struct dsp_section { @@ -31,8 +33,10 @@ }; /* Must define struct dsp_section before including the image. */ -#include "dsp_image_helloworld.h" +#include "dsp-image.h" +#define dsp_message (*(volatile struct ipc_message *)&DSP_(_status)) + #ifdef DEBUG static void dsp_status(void) { @@ -98,11 +102,13 @@ static void dsp_load(const struct dsp_section *im) { + unsigned int i; + while (im->raw_data_size_half) { volatile unsigned short *data_ptr = &DSP_(im->physical_addr); - unsigned int i; - /* Use 16-bit writes. */ + /* Use 16-bit writes. + TODO: Do this using HPIB DMAC. */ if (im->raw_data) { DEBUGF("dsp_load(): loading %u words at 0x%04x (0x%08lx)", im->raw_data_size_half, im->physical_addr, @@ -123,33 +129,184 @@ im++; } + +#ifdef REMAP_VECTORS + /* Copy relocated vectors (0x3f80) to where the ROM loader expects them + (0x7f80). + TODO: Un-hardcode 0x3f80. */ + for (i = 0; i < 0x80; i++) { + DSP_(0x7f80 + i) = DSP_(0x3f80 + i); + } +#endif } -void dsp_init(void) +static signed short *the_rover = (signed short *)0x1900000; +static unsigned int index_rover = 0; +static signed short __attribute__((aligned (16))) pcm_buffer[PCM_SIZE / 2]; + +void dsp_init() { + unsigned long sdem_addr; + int fd; + int bytes; + IO_INTC_IRQ0 = 1 << 11; IO_INTC_EINT0 |= 1 << 11; IO_DSPC_HPIB_CONTROL = 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7 | 1 << 3 | 1 << 0; dsp_reset(); - dsp_load(dsp_image_helloworld); + dsp_load(dsp_image); + + /* Initialize codec. */ + sdem_addr = (unsigned long)pcm_buffer - CONFIG_SDRAM_START; + DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx", + (unsigned long)pcm_buffer, (unsigned long)sdem_addr); + DSP_(_sdem_addrl) = sdem_addr & 0xffff; + DSP_(_sdem_addrh) = sdem_addr >> 16; + + fd = open("/rover.raw", O_RDONLY); + bytes = read(fd, the_rover, 4*1024*1024); + close(fd); + + DEBUGF("read %d rover bytes", bytes); + + #if 0 + { + unsigned int i; + memset(pcm_buffer, 0x80, PCM_SIZE); + for (i = 0; i < 8192; i++) { + signed short val = 0; + /*if (i < PCM_SIZE/4/2) { + val = 128*(i%256); + } else { + val = 2*128*128-128*(i%256); + }*/ + val = 128*(i%256); + pcm_buffer[2*i] = pcm_buffer[2*i+1] = val; + } + clean_dcache(); + + + { + unsigned int i; + volatile signed short *pdata = &DSP_(_data); + DEBUGF("dsp__data at %08x", pdata); + for (i = 0; i < 4096; i++) { + pdata[2*i]=pdata[2*i+1]=(i&1)*32767; + } + for (i = 4096; i < 8192; i++) { + pdata[2*i]=pdata[2*i+1]=0; + } + } + #endif + +#ifdef IPC_SIZES + DEBUGF("dsp_message at 0x%08x", &dsp_message); + DEBUGF("sizeof(ipc_message)=%uB offset(ipc_message.payload)=%uB", + sizeof(struct ipc_message), (int)&((struct ipc_message*)0)->payload); +#endif + +#ifdef INIT_MSG + /* Prepare init message. */ + + /* DSP accesses MUST be done a word at a time. */ + dsp_message.msg = MSG_INIT; + + sdem_addr = (unsigned long)pcm_sdram - CONFIG_SDRAM_START; + DEBUGF("pcm_sdram at 0x%08x, sdem_addr 0x%08x", pcm_sdram, sdem_addr); + dsp_message.payload.init.sdem_addrl = sdem_addr & 0xffff; + dsp_message.payload.init.sdem_addrh = sdem_addr >> 16; + + DEBUGF("dsp_message: %04x %04x %04x %04x", + ((unsigned short *)&dsp_message)[0], + ((unsigned short *)&dsp_message)[1], + ((unsigned short *)&dsp_message)[2], + ((unsigned short *)&dsp_message)[3]); +#endif } void DSPHINT(void) { unsigned int i; char buffer[80]; + static unsigned short level = 2; + unsigned short *pcm_topbottom, *pcm_topbottom_end; + IO_INTC_IRQ0 = 1 << 11; - /* DSP stores one character per word. */ - for (i = 0; i < sizeof(buffer); i++) { - buffer[i] = (&DSP_(_status))[i]; + switch (dsp_message.msg) { + case MSG_DEBUGF: + /* DSP stores one character per word. */ + for (i = 0; i < sizeof(buffer); i++) { + buffer[i] = dsp_message.payload.debugf.buffer[i]; + } + + /* Release shared area to DSP. */ + dsp_wake(); + + DEBUGF("DSP: %s", buffer); + break; + case MSG_REFILL: + DEBUGF("DSP: DMA0 with topbottom=%u (fill at %04lx)", + dsp_message.payload.refill.topbottom, + (unsigned long)pcm_buffer + + dsp_message.payload.refill.topbottom); + pcm_topbottom = pcm_buffer + dsp_message.payload.refill.topbottom / 2; + + /* + i = 0; + while (i < PCM_SIZE/4) { + unsigned int j; + for (j = 0; j < level; j++) { + pcm_topbottom[i+j] = -32768; + } + for (j = level; j < 2*level; j++) { + pcm_topbottom[i+j] = 32767; + } + i += 2*level; + } + + level += 2; + if (level > 256) { + level = 2; + }*/ + + memcpy(pcm_topbottom, the_rover + index_rover, PCM_SIZE/2); + index_rover += PCM_SIZE/4; + if (index_rover >= 2*1024*1024) { + index_rover = 0; + } + + /* + pcm_topbottom = &p_pcm_sdram[dsp_message.payload.refill.topbottom/2]; + DEBUGF("DSP: tofill begins: %04x %04x %04x %04x", + pcm_topbottom[0], + pcm_topbottom[1], + pcm_topbottom[2], + pcm_topbottom[3] + ); + pcm_topbottom_end = &p_pcm_sdram[(dsp_message.payload.refill.topbottom+PCM_SIZE/2)/2]; + DEBUGF("DSP: tofill ends: %04x %04x %04x %04x", + pcm_topbottom_end[-4], + pcm_topbottom_end[-3], + pcm_topbottom_end[-2], + pcm_topbottom_end[-1] + ); + */ + + /* + DEBUGF("DSP: DMA0: SD %04x:%04x -> DSP %04x:%04x, TRG %04x", + dsp_message.payload.refill._SDEM_ADDRH, + dsp_message.payload.refill._SDEM_ADDRL, + dsp_message.payload.refill._DSP_ADDRH, + dsp_message.payload.refill._DSP_ADDRL, + dsp_message.payload.refill._DMA_TRG); + */ + break; + default: + DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg); + break; } - - /* Release shared area to DSP. */ - dsp_wake(); - - DEBUGF("DSP: %s", buffer); } Index: firmware/target/arm/tms320dm320/dsp_image_helloworld.h =================================================================== --- firmware/target/arm/tms320dm320/dsp_image_helloworld.h (revision 15801) +++ firmware/target/arm/tms320dm320/dsp_image_helloworld.h (working copy) @@ -1,31 +0,0 @@ -#ifndef DSP_IMAGE_HELLOWORLD -#define DSP_IMAGE_HELLOWORLD -/* - * This is just a dummy DSP image so that dsp-dm320.c compiles. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 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 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -static const struct dsp_section dsp_image_helloworld[] = { - {NULL, 0, 0} -}; - -/* Symbol table, usable with the DSP_() macro (see dsp-target.h). */ -#define _status 0x0000 -#define _acked 0x0000 - -#endif