linux dsp gateway specification - sourceforge

126
1 (126) Linux DSP Gateway Specification Rev 3.3.1 Revision History Date Author SW Revision Doc Revision Description 16.05.2003 Toshihiro Kobayashi Kiyotaka Takahashi 1.0 - First Release 13.11.2003 Toshihiro Kobayashi 2.0 - Dynamic Loader Support 05.08.2004 Toshihiro Kobayashi - kernel 2.6 Support 20.08.2004 Toshihiro Kobayashi 2.0.1 a Error fix in example instruction 30.08.2004 Toshihiro Kobayashi 3.0 - mmap, interactive ioctl support dsptask multiple open support 04.10.2004 Toshihiro Kobayashi 3.0.1 - Without-devfs system support 02.11.2004 Toshihiro Kobayashi 3.0.2 - Bug fix (1MB export, proc read entries) 06.12.2004 Toshihiro Kobayashi 3.1 - Suspend / resume support 04.03.2005 Toshihiro Kobayashi 3.2 - Udev support 12.07.2005 Toshihiro Kobayashi 3.3 - PM enhanced 13.09.2006 Toshihiro Kobayashi Tetsuo Yamabe - OMAP2 support 13.11.2006 Tetsuo Yamabe 3.3.1 a Correct invalid index Copyright (c) 2003 - 2006 Nokia Corporation

Upload: others

Post on 01-Jan-2022

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Linux DSP Gateway Specification - SourceForge

1 (126)

Linux DSP Gateway Specification Rev 3.3.1

Revision History

Date Author SW Revision

Doc Revision

Description

16.05.2003 Toshihiro Kobayashi

Kiyotaka Takahashi

1.0 - First Release

13.11.2003 Toshihiro Kobayashi 2.0 - Dynamic Loader Support

05.08.2004 Toshihiro Kobayashi - kernel 2.6 Support

20.08.2004 Toshihiro Kobayashi

2.0.1

a Error fix in example instruction

30.08.2004 Toshihiro Kobayashi 3.0 - mmap, interactive ioctl support

dsptask multiple open support

04.10.2004 Toshihiro Kobayashi 3.0.1 - Without-devfs system support

02.11.2004 Toshihiro Kobayashi 3.0.2 - Bug fix (1MB export, proc read entries)

06.12.2004 Toshihiro Kobayashi 3.1 - Suspend / resume support

04.03.2005 Toshihiro Kobayashi 3.2 - Udev support

12.07.2005 Toshihiro Kobayashi 3.3 - PM enhanced

13.09.2006 Toshihiro Kobayashi

Tetsuo Yamabe

- OMAP2 support

13.11.2006 Tetsuo Yamabe

3.3.1

a Correct invalid index

Copyright (c) 2003 - 2006 Nokia Corporation

Page 2: Linux DSP Gateway Specification - SourceForge

2 (126)

1.1.1.1. INTRODUCTIONINTRODUCTIONINTRODUCTIONINTRODUCTION .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 5555

1.1. OVERVIEW................................................................................................................................................. 5 1.2. FEATURES ................................................................................................................................................. 5

2.2.2.2. DSP GATEWAY ARCHITECDSP GATEWAY ARCHITECDSP GATEWAY ARCHITECDSP GATEWAY ARCHITECTURETURETURETURE .................................................................................................................................................................................................................................................................................................................................................................................................................................................... 6666 2.1. MEMORY MAP ........................................................................................................................................... 6

2.1.1. DSP Internal Memories ................................................................................................................... 6 2.1.2. External Memory (SDRAM) Utilization.......................................................................................... 8 2.1.3. Memory Mapped IO (OMAP2)....................................................................................................... 10

2.2. INTER-PROCESSOR COMMUNICATION ...................................................................................................... 10 2.2.1. Mailbox mechanism in OMAP processor ...................................................................................... 10 2.2.2. Communication Buffer................................................................................................................... 11

2.3. MAILBOX COMMAND PROTOCOL .............................................................................................................. 16 2.3.1. Basic Concepts for the Protocol ..................................................................................................... 16 2.3.2. Bit Definitions for Mailbox Registers............................................................................................ 16 2.3.3. Mailbox Command Definition ....................................................................................................... 17

2.4. MAILBOX COMMAND SEQUENCE.............................................................................................................. 45 2.4.1. Configuration Sequence................................................................................................................. 45 2.4.2. Data Transfer Sequence ................................................................................................................ 46

3.3.3.3. LINUX APILINUX APILINUX APILINUX API .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... 52525252 3.1. OVERVIEW............................................................................................................................................... 52 3.2. DSP TASK DEVICES................................................................................................................................. 52

3.2.1. open() .............................................................................................................................................. 53 3.2.2. close().............................................................................................................................................. 54 3.2.3. read() .............................................................................................................................................. 54 3.2.4. write() ............................................................................................................................................. 55 3.2.5. poll(), select() .................................................................................................................................. 55 3.2.6. ioctl()............................................................................................................................................... 56 3.2.7. mmap() ........................................................................................................................................... 56

3.3. DSP CONTROL DEVICE............................................................................................................................ 57 3.3.1. ioctl()............................................................................................................................................... 57

3.4. DSP MEMORY DEVICE ............................................................................................................................ 59 3.4.1. lseek() ............................................................................................................................................. 59 3.4.2. read() .............................................................................................................................................. 59 3.4.3. write() ............................................................................................................................................. 60 3.4.4. ioctl()............................................................................................................................................... 60

3.5. DSP TASK WATCH DEVICE...................................................................................................................... 62 3.5.1. read() .............................................................................................................................................. 62 3.5.2. poll(), select() .................................................................................................................................. 63 3.5.3. ioctl()............................................................................................................................................... 63

3.6. DSP ERROR DETECTION DEVICE............................................................................................................. 64 3.6.1. read() .............................................................................................................................................. 64 3.6.2. poll(), select() .................................................................................................................................. 64

3.7. SYSFS ENTRIES FOR SETTING / GETTING STATUS..................................................................................... 64 3.7.1. cpustat............................................................................................................................................ 64 3.7.2. mblog .............................................................................................................................................. 64 3.7.3. ifver ................................................................................................................................................ 65 3.7.4. icrmask........................................................................................................................................... 65 3.7.5. mempool ......................................................................................................................................... 65 3.7.6. mmu................................................................................................................................................ 66 3.7.7. ipbuf................................................................................................................................................ 66 3.7.8. loadinfo........................................................................................................................................... 67 3.7.10. <dsptask[0-9]+>/devname.............................................................................................................. 67

Page 3: Linux DSP Gateway Specification - SourceForge

3 (126)

3.7.11. <dsptask[0-9]+>/devstate .............................................................................................................. 67 3.7.12. <dsptask[0-9]+>/taskname ............................................................................................................ 68 3.7.13. <dsptask[0-9]+>/ttyp...................................................................................................................... 68 3.7.14. <dsptask[0-9]+>/fifosz.................................................................................................................... 68 3.7.15. <dsptask[0-9]+>/fifocnt .................................................................................................................. 68 3.7.16. <dsptask[0-9]+>/ipblink................................................................................................................. 68 3.7.17. <dsptask[0-9]+>/wsz ...................................................................................................................... 69 3.7.18. <dsptask[0-9]+>/proc_list .............................................................................................................. 69

3.8. HEADER FOR APPLICATIONS.................................................................................................................... 69 4.4.4.4. LINUX DRIVER OVERVIELINUX DRIVER OVERVIELINUX DRIVER OVERVIELINUX DRIVER OVERVIEW AND SYSTEM CONFIGUW AND SYSTEM CONFIGUW AND SYSTEM CONFIGUW AND SYSTEM CONFIGURATIONRATIONRATIONRATION............................................................................................................................................................................................................................................ 70707070

4.1. OVERVIEW............................................................................................................................................... 70 4.2. KERNEL CONFIGURATION........................................................................................................................ 70 4.3. DEVICE FILES.......................................................................................................................................... 71

4.3.1. udev ................................................................................................................................................ 71 4.3.2. Manual Setup................................................................................................................................. 72

5.5.5.5. DSP PROGRAMMINGDSP PROGRAMMINGDSP PROGRAMMINGDSP PROGRAMMING ............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ 73737373 5.1. OVERVIEW............................................................................................................................................... 73 5.2. TOOLCHAIN ............................................................................................................................................. 73 5.3. DSP TASK PROGRAMMING....................................................................................................................... 73 5.4. TASK TYPE .............................................................................................................................................. 74

5.4.1. Active Sending / Passive Sending.................................................................................................. 74 5.4.2. Active Receiving / Passive Receiving............................................................................................. 75 5.4.3. Word Sending / Block Sending ...................................................................................................... 75 5.4.4. Word Receiving / Block Receiving ................................................................................................. 75 5.4.5. Global Block Sending / Private Block Sending ............................................................................. 75 5.4.6. Global Block Receiving / Private Block Receiving ........................................................................ 75

5.5. DSPTASK STRUCTURE MEMBERS .............................................................................................................. 76 5.6. TASK API ................................................................................................................................................ 79 5.7. GLOBAL IPBUF ALLOCATION / FREEING RULE ....................................................................................... 83 5.8. TIMER QUEUE ......................................................................................................................................... 83 5.9. POLLING MECHANISM ............................................................................................................................. 83 5.10. ENDIANISM.............................................................................................................................................. 84 5.11. SYSTEM PARAMETERS ............................................................................................................................. 85 5.12. EXAMPLE................................................................................................................................................. 85

5.12.1. sysinfo.c .......................................................................................................................................... 85 5.12.2. task_test2.c .................................................................................................................................... 86 5.12.3. ex_task.cmd.................................................................................................................................... 87 5.12.4. Makefile.......................................................................................................................................... 87 5.12.5. Make............................................................................................................................................... 88

6.6.6.6. DSP GATEWAY SYSTEM KDSP GATEWAY SYSTEM KDSP GATEWAY SYSTEM KDSP GATEWAY SYSTEM KERNEL OVERVIEWERNEL OVERVIEWERNEL OVERVIEWERNEL OVERVIEW ................................................................................................................................................................................................................................................................................................................................................ 89898989 6.1. OVERVIEW............................................................................................................................................... 89 6.2. DSP/BIOS ENTITIES ............................................................................................................................... 89

6.2.1. HWI ................................................................................................................................................ 89 6.2.2. TSK................................................................................................................................................. 90 6.2.3. PRD ................................................................................................................................................ 90

7.7.7.7. DSP PROGRAM EXECUTIODSP PROGRAM EXECUTIODSP PROGRAM EXECUTIODSP PROGRAM EXECUTION ON THE TARGET MACHN ON THE TARGET MACHN ON THE TARGET MACHN ON THE TARGET MACHINEINEINEINE ................................................................................................................................................................................................................................................................ 92929292 7.1. FILES TO BE PREPARED ON ARM(LINUX) SIDE......................................................................................... 92 7.2. DSP-ENABLED PROGRAM EXECUTION ...................................................................................................... 92

7.2.1. DSP program loading and starting ............................................................................................... 92 7.2.2. Test Run......................................................................................................................................... 93

REFERENCESREFERENCESREFERENCESREFERENCES............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ 94949494

Page 4: Linux DSP Gateway Specification - SourceForge

4 (126)

APPENDIX A: APPENDIX A: APPENDIX A: APPENDIX A: dspctldspctldspctldspctl UTILITY UTILITY UTILITY UTILITY........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ 95959595 1) START .......................................................................................................................................................... 95 2) STOP............................................................................................................................................................ 96 3) VERSION ...................................................................................................................................................... 97 4) LOAD ........................................................................................................................................................... 97 5) RUN (= UNRESET) / RESET ............................................................................................................................ 97 6) SETRSTVECT (FOR DEBUG USE) .................................................................................................................... 97 7) GBL_IDLE / CPU_IDLE (ONLY FOR OMAP1) .................................................................................................. 97 8) SUSPEND, RESUME....................................................................................................................................... 97 9) DSPCFG, DSPUNCFG ..................................................................................................................................... 97 10) POLL........................................................................................................................................................ 97 11) KMEM_RESERVE, KMEM_RELEASE ........................................................................................................... 98 12) EXMAP, EXUNMAP .................................................................................................................................... 98 13) MAPFLUSH ..............................................................................................................................................100 14) FBEXPORT...............................................................................................................................................101 15) MMUINIT.................................................................................................................................................102 16) MMUITACK (FOR DEBUG USE) ..................................................................................................................102 17) MKDEV, RMDEV (FOR DEBUG USE) ...........................................................................................................102 18) TADD, TDEL (FOR DEBUG USE).................................................................................................................102 19) GETVAR, SETVAR.....................................................................................................................................102 20) REGREAD, REGWRITE (FOR DEBUG USE) ..................................................................................................103 21) RUNLEVEL ..............................................................................................................................................103 22) MBSEND (FOR DEBUG USE) ......................................................................................................................103

APPENDIX B: DSP TASKAPPENDIX B: DSP TASKAPPENDIX B: DSP TASKAPPENDIX B: DSP TASK EXAMPLES AND MAILBO EXAMPLES AND MAILBO EXAMPLES AND MAILBO EXAMPLES AND MAILBOX COMMAND EXCHANGEX COMMAND EXCHANGEX COMMAND EXCHANGEX COMMAND EXCHANGE COMMENTARY COMMENTARY COMMENTARY COMMENTARY.................................... 104104104104 1) DSP CONFIGURATION.................................................................................................................................104 2) TEST1 .........................................................................................................................................................105 3) TEST2 .........................................................................................................................................................107 4) TEST3 .........................................................................................................................................................108 5) TEST4 .........................................................................................................................................................110 6) TEST7 .........................................................................................................................................................113 7) TASK8.........................................................................................................................................................116 8) HELLOTIMER ..............................................................................................................................................122

Page 5: Linux DSP Gateway Specification - SourceForge

5 (126)

1. INTRODUCTION

1.1. Overview

Some of Texas Instruments’ OMAP family processors, such as OMAP1510 or OMAP2420, have an integrated DSP (Digital Signal Processor) as the multimedia accelerator on the die, along with the main MPU (ARM9 or ARM11). DSP Gateway is an open-sourced bridge software which provides communication method between the MPU and the DSP for the Linux system. The DSP Gateway consists of two parts, the one is a Linux device driver on the ARM and the other is a DSP-side kernel library, and they communicate with each other. The Linux part provides conventional Linux device driver interface so the application can use DSP functions through normal system calls such as read() and write(). The DSP kernel library part provides multi-task environment and APIs for user tasks, which can be controlled from Linux. This document describes the communication protocol between two processors, APIs for Linux application and DSP tasks, summaries of the Linux driver and the DSP library and an example of the DSP task. Additionally, the manual for the DSP control utility and the commentary of the inter-processor communication in the DSP Gateway are attached as appendixes. 1.2. Features

The features of the DSP Gateway are summarized as followings. ♦ Familiar APIs for Linux applications, using conventional Linux device file interfaces. ♦ Multi-task environment for DSP applications, by virtue of the TI’s DSP/BIOS. ♦ Minimum copy count for maximum throughput in data exchange between the ARM and the DSP. ♦ Memory extension feature for DSP, i.e. external memory mapping for the DSP space. ♦ /proc file entries for debugging and run-time environment configurations. ♦ Power Management functions for DSP. ♦ Error detection on DSP.

Page 6: Linux DSP Gateway Specification - SourceForge

6 (126)

2. DSP GATEWAY ARCHITECTURE

2.1. Memory Map

2.1.1. DSP Internal Memories

OMAP DSP has three types of dedicated internal memory, DARAM (Dual Access Memory), SARAM (Single Access Memory) and PDROM (Program and Data ROM). DARAM and SARAM are seen in the DSP memory space and also in the MPU memory space. PDROM is not accessible from the MPU and not used in the DSP Gateway. See Table 2-1 and Figure 2-1 for more details in DSP internal memories..

Table 2-1: Mappings of DSP Internal Memories

Memory DSP Address

MPU Physical Address

Linux Virtual Address size

DARAM 0x000000

| 0x00ffff

0xe0000000 |

0xe000ffff

0xe0000000 |

0xe000ffff 64kB

SARAM 0x010000

| 0x027fff

0xe0010000 |

0xe0027fff

0xe0010000 |

0xe0027fff 96kB

OMAP1 (15xx, 16xx, 1710, 5910, 5912) PDROM

0xff8000 |

0xffffff

(not seen)

32kB

DARAM 0x000000

| 0x00ffff

0x58000000 |

0x5800ffff

0xe0000000 |

0xe000ffff 64kB

SARAM 0x010000

| 0x027fff

0x58010000 |

0x58027fff

0xe0010000 |

0xe0027fff 96kB OMAP2

(2420)

PDROM 0xff0000

| 0xffffff

(not seen)

64kB

Page 7: Linux DSP Gateway Specification - SourceForge

7 (126)

Figure 2-1: DSP Internal Memories visibility

00_0000 DARAM SARAM

PDROM DSP Memory Space

Linux Virtual Address Space

0000_0000

ffff_ffff

e000_0000

SARAM DARAM

e0ff_ffff ff_ffff

DSP space shadow area

As shown in Figure 2-1, 0xe0000000 - 0xe0ffffff in the Linux virtual address space is defined as DSP space shadow area. Whole 16MB of the DSP space is shadowed to this area, except for the PDROM.

Page 8: Linux DSP Gateway Specification - SourceForge

8 (126)

2.1.2. External Memory (SDRAM) Utilization

External memory (SDRAM) can also be used from DSP by programming the DSP MMU to map some area in the DSP space to there. Using this feature, DSP application programmer can extend the available memory area for code and data which is confined in 192kB by default. The DSP MMU programming is done by the MPU. In DSP Gateway, when a memory block is exported to DSP, it is also exported to the corresponding address in the DSP space shadow area in the Linux virtual address space, so that that area still looks as a ‘shadow’ of the DSP space (Figure 2-2). Using this area, address exchanges between DSP space and Linux virtual address space can be done simply with a base address conversion.

Figure 2-2: SDRAM mapping for DSP space

SDRAM

00_0000 DARAM SARAM

PDROM DSP Memory Space

Linux Virtual Address Space

0000_0000

C000_0000

Physical Memory

E000_0000

SARAM DARAM

E100_0000 FF_FFFF

DSP space shadow area

Kernel memory area MPU MMU

DSP MMU

Page 9: Linux DSP Gateway Specification - SourceForge

9 (126)

Before releasing the DSP from reset, the reset vector at address 0xffff00 should be set so that the DSP program can jump to the start address of the application code. By default, this address is in PDROM area, which cannot be modified by user. In the DSP Gateway driver, a 4k-page of external SDRAM memory is allocated and mapped to the DSP space covering the DSP vector table (i.e. 0xfff000-0xffffff), overriding the PDROM (Figure 2-3).

Figure 2-3: SDRAM mapping for Reset Vector

SDRAM

00_0000 DARAM SARAM

PDROM DSP Memory Space

Linux Virtual Address Space

0000_0000

C000_0000

Physical Memory

E000_0000

SARAM DARAM

E100_0000 FF_FFFF

DSP space shadow area

Kernel memory area MPU MMU

DSP MMU

Page 10: Linux DSP Gateway Specification - SourceForge

10 (126)

2.1.3. Memory Mapped IO (OMAP2)

DSP subsystem equips 16MB data/program memory space and 128kB I/O memory space. On OMAP2, I/O memory space is mapped onto 16MB memory space by MMU; and it can be accessed through normal instructions. Also mapping placement is programmable via an IOMA register, so DSP developer can adjust the size of I/O memory space to access several L4 peripherals (e.g. mailbox and timer registers). IOMA register represents the base address of I/O address mapping; and is set to 0xFC0000 in DSP Gateway. In this case, DSP can have up to 34 of accessibilities to L4 peripherals. Find more detail about DSP memory mapping in [5]. 2.2. Inter-Processor Communication

2.2.1. Mailbox mechanism in OMAP processor

The ARM-DSP interprocessor communication is implemented as the mechanism called ‘mailbox’ in OMAP devices. In OMAP1 series, there are three sets of mailbox registers: one for the MPU to send messages and issue an interrupt to DSP, the other two for DSP to send messages and issue an interrupt to the MPU. Each set of mailbox registers consists of two 16-bit registers (cmd and data) and a 1-bit flag register so the one processor can send a total of 32 bit data to the other, through the mailbox register. The DSP Gateway uses one mailbox for each direction as shown in Figure 2-4, i.e. one mailbox for DSP to ARM direction is not used.

Figure 2-4: Mailbox mechanism (OMAP1)

DSP MPU

INT5

IRQ10

IRQ11

(not used)

ARM2DSP1 mailbox (16bit cmd + 16bit data)

DSP2ARM1 mailbox (16bit cmd + 16bit data)

DSP2ARM2 mailbox (16bit cmd + 16bit data)

Mailbox registers

On the other hand, OMAP2 series has a different mailbox mechanism, as shown in Figure 2-5. There are 6 sets of mailbox registers, and each message register can carry a 32-bit data. As the mailbox is an L4 peripherals, any of ARM, DSP, and IVA can use it via L4 interconnect. In DSP Gateway, two mailbox queues are reserved, MAILBOX_0 for ARM to DSP direction and MAILBOX_1 for DSP to ARM direction. The mailbox protocol used in DSP Gateway is described in Chapter 2.3.

Page 11: Linux DSP Gateway Specification - SourceForge

11 (126)

Figure 2-5: Mailbox mechanism (OMAP2)

DSP

MPU

INT5

IRQ26 MAILBOX_0

(32bit message queue)

MAILBOX_1 (32bit message queue)

Mailbox registers

MAILBOX_2 MAILBOX_3 MAILBOX_4 MAILBOX_5

L4 interconnect

2.2.2. Communication Buffer

It is not effective, even unrealistic to transfer a large amount of data between two processors through the mailbox registers. Therefore, IPBUF (Inter-Processor Buffer) is introduced for the large block data transfer. The IPBUF can be placed at either the DSP internal memories (DARAM and SARAM), or the external SDRAM block which is exported to the DSP space. DSP Gateway defines three types of IPBUFs: Global IPBUF, Private IPBUF and System IPBUF. 2.2.2.1. Global IPBUF

The Global IPBUFs are defined for the task-level block data transfer between ARM and DSP. The Global IPBUF lines are identified with BID (Buffer ID), and all tasks can use them commonly. The maximum line size is 64k words (128k bytes). Each IPBUF line has 6-words header, which contains valid data size, owner task information and sync words. An example of the Global IPBUF structure is shown in Figure 2-6.

Figure 2-6: An example of Global IPBUF structure header(6words) (word address) 0x000100

0x000185 IPBUF0 (128 words)

header(6words) 0x000186

0x00020b IPBUF1 (128 words) header(6words) 0x00020c

0x000291 IPBUF2 (128 words)

header(6words) 0x000292

0x000317 IPBUF3 (128 words)

The Global IPBUF header contains a word of the valid data count, an IPBLINK word, and two sets of a lock word and a sync word each for ARM and DSP (Figure 2-7). For future expansion, note that the data body should be aligned at the long word (4-bytes) boundary in order to transfer long words between ARM and DSP.

Page 12: Linux DSP Gateway Specification - SourceForge

12 (126)

Figure 2-7: Global IPBUF structure (detail)

(word offset) 0x00 valid data count 0x01 next BID in IPBLINK 0x02 ARM side lock info 0x03 ARM side sync word 0x04 DSP side lock info 0x05 DSP side sync word

header

0x06

0x83

data body (128 words)

data body

The ARM side lock info field indicates to which DSP task ARM has sent the block data using this IPBUF line. The value of 0xfe is reserved as anonymous task and 0xff is the indication that this line is free. In the same way, the DSP side lock info is used by DSP side to indicate which task has sent the block data to ARM using this IPBUF line. The ARM side and DSP side sync words are used to make sure read-after-write operation between the processors. The receiver processor should not read the data from this IPBUF until the sync word indicates that the data write has been completed by the sender processor. Both processors will try to maintain their own buffer line count balanced between as far as possible. The Global IPBUF lines are managed with the IPBLINK. This mechanism is used for the free IPBUF pool in both ARM and DSP, and read buffer link in ARM side. The read buffer link is not equipped in DSP side. See the IPBLINK structure (Figure 2-8) and an example of buffer ownership transition sequence (Figure 2-9).

Figure 2-8: IPBLINK structure

IPBLINK head top = 1 tail = 3 next = 2

IPBUF 1

next = 3

IPBUF 2

next = NULL

IPBUF 3

Figure 2-9: An example of Global IPBUF ownership transition sequence

Page 13: Linux DSP Gateway Specification - SourceForge

13 (126)

ARM

2 3

n IPBUF n

(1) initial state free pool

task0

read link

task1 task2

read link

read link

DSP

0 1

free pool

task0 task1 task2

ARM

3

(2) task0 in DSP reserved buffer 0 from the free pool and writes data to it

free pool

task0

read link

task1 task2

read link

read link

DSP

1

free pool

task0 task1 task2

2 0

ARM

3

(3) DSP sends data with buffer 0 to ARM. Buffer 0 is linked to task0 read link.

free pool

task0

read link

task1 task2

read link

read link

DSP

0 1

free pool

task0 task1 task2

2

ARM

3

(4) ARM reads data from buffer 0, besides yielding buffer 2 to DSP

free pool

task0

read link

task1 task2

read link

read link

DSP

0 1

free pool

task0 task1 task2

2

Page 14: Linux DSP Gateway Specification - SourceForge

14 (126)

ARM

3

(5) buffer 0 is returned to the free pool

free pool

task0

read link

task1 task2

read link

read link

DSP

0 1

free pool

task0 task1 task2

2

When an IPBUF is sent from one to the other, the receiving processor will yield one buffer ownership to the sending processor in return as (4) above. 2.2.2.2. Private IPBUF

DSP tasks can have their Private IPBUF. The structure is different from Global IPBUF as shown in Figure 2-10. The address of the IPBUF data body can be changed in every data transfer. Only Active Receiving tasks can use the Private IPBUF for data receiving from ARM, since it needs to inform the address of the buffer data body to ARM before ARM sends data to DSP.

Page 15: Linux DSP Gateway Specification - SourceForge

15 (126)

Figure 2-10: Private IPBUF structure

(word offset) 0x00 valid count 0x01 sync word 0x02 lower 0x03

data body address upper

header

(address specified

in the header)

data body data body

The sync word field is used to make sure read-after-write operation between the processors. The sending processor sets the TID of this task to this field after writing the data to this IPBUF. The receiver processor should not read the data from this IPBUF until the sync word becomes that TID. After reading, the receiver processor writes 0xff to this field to indicate this buffer is free. After that, the sending processor can use this IPBUF again. The reason why the header and the data body are separated for Private IPBUF is for the situation in which the data needs to be written at the middle of the buffer block, like (Figure 2-11).

Figure 2-11: Valid data at middle of the Private IPBUF

header

buffer block

(data needs to be written here)

address

2.2.2.3. System IPBUF

The system IPBUF is defined for the system data delivery for each direction (ARM to DSP and DSP to ARM). They are used to send extra data along with the Mailbox command. The System IPBUF structure is shown in Figure 2-12.

Figure 2-12: System IPBUF

(word offset) 0x00 sync word 0x01

0x0f

data (15 words)

Page 16: Linux DSP Gateway Specification - SourceForge

16 (126)

It should be noted that the System IPBUF needs to be placed at external memory, for DSP global idling. If any of two System IPBUFs are placed on internal memory (i.e. DARAM or SARAM), DMA and PLL domains in DSP will be always awake and never go into idle state. 2.3. Mailbox Command Protocol

2.3.1. Basic Concepts for the Protocol

Followings are essential ideas or concepts to understand the Mailbox protocol in the DSP Gateway. ♦ Tasks in the DSP are identified with TID (Task ID), and Most commands are sent with the TID. ♦ IPBUFs are used for the block data transfer between ARM and DSP. ♦ An IPBUF is owned by either processors. Only the processor which has the ownership of the IPBUF

can access to that IPBUF. When a data transfer with an IPBUF is performed, the ownership of the IPBUF moves to the recipient.

2.3.2. Bit Definitions for Mailbox Registers

Bit definitions of mailbox command and data registers are shown in Figure 2-13. In OMAP1, there are 2 set of 16-bit registers, mailbox command/data register (Figure 2-13 (a)). On the other hand, these two registers are integrated to a single 32-bit register in OMAP2, called Mailbox Message Register (Figure 2-13 (b)). However, their fundamental function, or usage is the same each other except storage format. It is defined so that the upper/lower part of the mailbox message register corresponds to mailbox command/data respectively. Then, from this section, a description of mailbox data/command register will be replaced by the upper/lower half of mailbox message register for DSP Gateway of OMAP2 in the manner of Figure 2-13. The Q bit (command register bit [15]) is toggled on each command transmission, in order to distinguish the command from previous one. This is a workaround operation for potential problem of the mailbox interrupt mechanism – In some situation (on OMAP1), two mailbox interrupts are observed on ARM even DSP writes to mailbox registers only once.

Figure 2-13: Mailbox Message Bit Definitions

(a) OMAP1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register

(16-bit) Q CMD_H CMD_L 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register

(16-bit) DATA

(b) OMAP2 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 Q CMD_H CMD_L 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Message Register (32-bit)

DATA

Where the abbreviations used in the above figures represent following descriptions. Name Description Q sequence number CMD_H command primary bits (Defined in 2.3.3) CMD_L command option bits

Page 17: Linux DSP Gateway Specification - SourceForge

17 (126)

2.3.3. Mailbox Command Definition

7-bit mailbox commands are defined as Table 2-2. These commands are sent on CMD_H field (bits [14:8]) in the command register, along with supplementary information on CMD_L bits and data register.

Table 2-2: Mailbox Command Definition

Command CMD_H CMD_L DATA Short Description WDSND 0x10 TID word data to send Word Send WDREQ 0x11 TID - Word Request BKSND 0x20 TID BID Block Send BKREQ 0x21 TID requesting count Block Request BKYLD 0x23 - BID Block Yield BKSNDP 0x24 TID - Block Send Private BKREQP 0x25 TID - Block Request Private TCTL 0x30 TID ctlcmd / return value Task Control TCTLDATA 0x31 - data Task Control Data POLL 0x32 - - Poll RUNLEVEL 0x51 RUNLEVEL - DSP Runlevel Switch PM 0x52 PMCMD mask Power Management SUSPEND 0x53 - - Suspend TCFG 0x60 TID configuration data Task Configuration TADD 0x62 TID - Task Add TDEL 0x63 TID type Task Delete TSTOP 0x65 - - Task Stop DSPCFG 0x70 CFGTYP configuration data System Configuration REGRW 0x72 TYPE address / data Register Read / Write GETVAR 0x74 VARID data Get Variable SETVAR 0x75 VARID data Set Variable ERR 0x78 EID command caused

the error Error Information

DBG 0x79 TID - Debug

Page 18: Linux DSP Gateway Specification - SourceForge

18 (126)

2.3.3.1. WDSND

Word Send. The initiating processor sends a 16-bit data on the mailbox data register to the target processor. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 0 1 0 0 0 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register DATA

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x10 command[7:0] TID DSP task ID data[15:0] DATA 1-word sending data

Page 19: Linux DSP Gateway Specification - SourceForge

19 (126)

2.3.3.2. WDREQ

Word Request. The initiating processor requests a 16-bit data and the target processor should respond with WDSND command to this request. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 0 1 0 0 0 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x11 command[7:0] TID DSP task ID data[15:0] don’t care

Page 20: Linux DSP Gateway Specification - SourceForge

20 (126)

2.3.3.3. BKSND

Block Send. The initiating processor sends a block data to the target processor using the Global IPBUF. With this command the ownership of this IPBUF line moves to the target processor. The valid word count is indicated in the IPBUF header. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 0 0 0 0 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register BID

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x20 command[7:0] TID DSP task ID data[15:0] BID IPBUF ID

Page 21: Linux DSP Gateway Specification - SourceForge

21 (126)

2.3.3.4. BKREQ

Block Request. The initiating processor requests a block data using the Global IPBUF or the Private IPBUF and the target processor should respond with BKSND or BKSNDP command to this request. The word number requested in this command is a suggestion to the target processor. The target processor decides how many words to send according to this information, but it should not be more than requested count. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 0 0 0 0 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register CNT

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x21 command[7:0] TID DSP task ID data[15:0] CNT requesting word count (suggestion)

Page 22: Linux DSP Gateway Specification - SourceForge

22 (126)

2.3.3.5. BKYLD

Block Yield. The initiating processor can yield the ownership of a Global IPBUF line to the target processor with this command. This command may be issued in response to a BKSND command. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 0 0 0 1 1 don't care 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register BID

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x23 command[7:0] don't care data[15:0] BID IPBUF ID

Page 23: Linux DSP Gateway Specification - SourceForge

23 (126)

2.3.3.6. BKSNDP

Block Send Private. The initiating processor sends a block data to the target processor using the Private IPBUF. The valid word count should be indicated in the IPBUF header. ARM can issue this command only in response to the BKREQP command from DSP. DSP can issue this command at any time (as long as the Private IPBUF is free). See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 0 0 1 0 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x24 command[7:0] TID DSP task ID data[15:0] don’t care

Page 24: Linux DSP Gateway Specification - SourceForge

24 (126)

2.3.3.7. BKREQP

Block Request Private. DSP requests a block data using the Private IPBUF and ARM should respond with BKSNDP command to this request. ARM uses BKREQ command even if the corresponding task is Private Sending task, and should not issue this command. DSP should set the requesting word number in the Private IPBUF header before sending this command to ARM. When ARM received this command, it reads the count information in the IPBUF and decides how many words to send regarding this information, but it should not be more than requested count. See 2.4.1.3 for the data transfer sequence. Direction

ARM to DSP no DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 0 0 1 0 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x25 command[7:0] TID DSP task ID data[15:0] don’t care

Page 25: Linux DSP Gateway Specification - SourceForge

25 (126)

2.3.3.8. TCTL

Task Control. ARM sends the task control commands to DSP, and DSP sends back the return value to ARM (if necessary). The DSP action to take at receiving this command is task dependent. The definition of the commands are shown below. The user can define TCTL commands in the ranges of 0x8000 – 0x81ff and 0x9000 – 0x91ff. Additionally, the command range of 0x80 – 0xff is also user-defined. but it is kept for the backward compatibility. The user should not define any commands in this range newly. If the TCTL command being sent has an argument, it is sent using the System IPBUF. Direction

ARM to DSP yes DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 1 0 0 0 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register CTLCMD or RETVAL

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x30 command[7:0] TID DSP task ID

CTLCMD (ARM to DSP) control command data[15:0] RETVAL (DSP to ARM) return value

Configuration data structure (on the System IPBUF)

Word Name Description 1 arg1 Argument 1

Page 26: Linux DSP Gateway Specification - SourceForge

26 (126)

CTLCMD definition

Code Range Description 0x0000 – 0x007f System Command

0x0000 TINIT Task Initialize 0x0001 TEN Task Enable 0x0002 TDIS Task Disable 0x0003 TCLR Task Clear 0x0004 TKILL Task Kill

0x0005 | 0x007f

Reserved

0x0080 – 0x00ff User-defined (No parameter, No return value) This range is kept for backward compatibility. DO NOT define new commands in this range.

0x0100 - 0x7fff Reserved 0x8000 - 0x80ff User-defined (No parameter, No return value) 0x8100 - 0x81ff User-defined (1 argument, No return value) 0x8200 - 0x8fff Reserved 0x9000 - 0x90ff User-defined (No parameter, have a return value) 0x9100 - 0x91ff User-defined (1 argument, have a return value) 0x9200 - 0xffff Reserved

Page 27: Linux DSP Gateway Specification - SourceForge

27 (126)

2.3.3.9. TCTLDATA

Task Control Data. This command is used only in DSP internally. This is additional parameter for the TCTL commands which takes an argument. Direction

ARM to DSP no DSP to ARM no

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register 0 1 1 0 0 0 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register DATA

Bit Name Description command[15] don’t care command[14:8] CMD_H 0x31 command[7:0] don’t care data[15:0] DATA parameter for TCTL

Page 28: Linux DSP Gateway Specification - SourceForge

28 (126)

2.3.3.10. POLL

Poll. ARM sends the poll commands to DSP, and DSP sends back the response to ARM. The mailbox protocol doesn’t define when DSP can return the POLL response, but ideally it should be after all DSP task’s availability is confirmed. Direction

ARM to DSP Yes (request) DSP to ARM Yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 0 1 1 0 0 1 0 don’t care 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x32 command[7:0] don’t care data[15:0] don’t care

Page 29: Linux DSP Gateway Specification - SourceForge

29 (126)

2.3.3.11. RUNLEVEL

DSP Runlevel Switch. The user can switch the DSP system runlevel. There are three runlevels, USER, SUPER and RECOVERY. The USER runlevel is normal mode, on which all user tasks can run. The SUPER runlevel is the supervisor mode, on which only the super task can run. All user tasks become pending on this runlevel. The RECOVERY runlevel is same as SUPER, except that the DSP sends debug information of the erring task. This mode is used when DSP MMU error is detected on ARM. Direction

ARM to DSP yes DSP to ARM no

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 0 1 0 0 0 1 RUNLEVEL 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x51 command[7:0] RUNLEVEL Runlevel to switch data[15:0] don’t care

RUNLEVEL description

Name RUNLEVEL Description USER 0x01 Normal mode. SUPER 0x0e Supervisor mode. No user task can run. RECOVERY 0x10 Recovery mode. DSP sends debug information about the

erring task.

Page 30: Linux DSP Gateway Specification - SourceForge

30 (126)

2.3.3.12. PM

Power Management. This command is used to allow or prohibit domains in DSP to stop when DSP enters idle mode. When this command is sent with PMCMD=ENABLE, domains indicated in MASK will be prohibited to stop even if DSP enters idle. On the other hand, when this command is sent with PMCMD=DISABLE, domains indicated in MASK can stop in conjunction with the DSP idle. DSP-side program is expected to support multiple enabling / disabling. In practice, this command is used to keep awake DMA domain to allow ARM to access to DSP internal memories. Direction

ARM to DSP yes DSP to ARM no

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 0 1 0 0 1 0 PMCMD 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register MASK

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x52 command[7:0] PMCMD Power management command data[15:0] MASK Mask of domain of interest

PMCMD description

Command PMCMD Description DISABLE 0x00 Allow to stop ENABLE 0x01 Prohibit to stop when DSP enters idle

MASK description

MASK bit definitions are derived from DSP Idle Configuration Register (ICR).

MASK bit definition in OMAP1 bit NAME Description 15:6 Reserved 5 DSPREG_ICR_EMIF EMIF 4 DSPREG_ICR_DPLL DPLL 3 DSPREG_ICR_PER peripherals 2 DSPREG_ICR_CACHE I-cache 1 DSPREG_ICR_DMA DMA controller 0 DSPREG_ICR_CPU CPU core and memory

Page 31: Linux DSP Gateway Specification - SourceForge

31 (126)

MASK bit definition in OMAP2 bit NAME Description 15:10 Reserved 9 DSPREG_ICR_HWA Hardware accelerators 8 DSPREG_ICR_IPORT Instruction port 7 DSPREG_ICR_MPORT Memory port 6 DSPREG_ICR_XPORT External peripheral port 5 DSPREG_ICR_DPORT Data port 4 DSPREG_ICR_DPLL DPLL 3 DSPREG_ICR_PER Peripherals 2 DSPREG_ICR_CACHE I-cache 1 DSPREG_ICR_DMA DMA controller 0 DSPREG_ICR_CPU DSP

2.3.3.13. SUSPEND

Suspend. ARM requests DSP to suspend with this command. When DSP received this command, it saves register contents to the memory, sets its own reset vector to the pointer of the resume code, then returns SUSPEND response to ARM and hangs up. When ARM receives the SUSPEND response, it can reset DSP. After then, when DSP needs to be resumed, ARM can just release the DSP’s reset so the DSP runs resume code which restores the saved register contents, and gets back to the normal operation. Direction

ARM to DSP yes (request) DSP to ARM yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 0 1 0 0 1 1 don’t care 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x53 command[7:0] don’t care data[15:0] don’t care

Page 32: Linux DSP Gateway Specification - SourceForge

32 (126)

2.3.3.14. TCFG

Task Configuration Request/Response. ARM requests task configuration information with this command. DSP should respond to the request also by this command, with configuration data in the System Buffer. See 2.4.1.2 for the configuration sequence. Direction

ARM to DSP yes (request) DSP to ARM yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 0 0 0 0 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x60 command[7:0] TID DSP task ID data[15:0] don’t care

Configuration data structure (on the System IPBUF)

Word Name Description task type information Bit Name Description 15:6 RFU reserved (SBZ) 5 PVDM private buffer for DSP->MPU 4 PVMD private buffer for MPU->DSP 3 BKDM block transfer for DSP -> MPU 2 BKMD block transfer for MPU -> DSP 1 ASND active send

0 ttyp

0 ARCV active receive 1 upper 7 bits 2

ipb_dm lower 16 bits

private IPBUF header address (word address) for DSP->MPU direction

3 upper 7 bits 4

ipb_md lower 16 bits

private IPBUF header address (word address) for MPU->DSP direction

5 upper 7 bits 6

mapstart lower 16 bits

base address of the mmap buffer

7 upper 7 bits 8

maplen lower 16 bits

size of the mmap buffer (in word)

9 upper 7 bits 10

tnm lower 16 bits

address of the task name string

Page 33: Linux DSP Gateway Specification - SourceForge

33 (126)

♦ ttyp

Bit definitions of ttyp (task type information) are shown below.

PVDM (bit 5): block transfer using private IPBUF for DSP->MPU 1: This task uses BKSNDP command for DSP -> MPU data transfer. 0: This task uses BKSND or WDSND command for DSP -> MPU data transfer.

PVMD (bit 4): block transfer using private IPBUF for MPU -> DSP 1: This task accepts BKSNDP command for MPU -> DSP data transfer. 0: This task doesn’t accepts BKSNDP command but use BKSND or WDSND command

for MPU -> DSP data transfer.

BKDM (bit 3): block transfer for DSP->MPU 1: This task uses BKSND or BKSNDP command for DSP -> MPU data transfer. 0: This task uses WDSND command for DSP -> MPU data transfer.

BKMD (bit 2): block transfer for MPU -> DSP 1: This task accepts BKSND or BKSNDP command for MPU -> DSP data transfer. 0: This task doesn’t accepts neither BKSND nor BKSNDP command but use WDSND

command for MPU -> DSP data transfer.

ASND (bit 1): active send 1: This task issues WDSND/BKSND command spontaneously and MPU doesn’t need to

issue WDREQ/BKREQ command to DSP. 0: This task issues WDSND/BKSND command only in response to the WDREQ/BKREQ

command from MPU.

ARCV (bit 1): active receive 1: This task issues WDREQ/BKREQ command when it needs data from MPU. MPU

should not issue WDSND/BKSND command to this task without receiving WDREQ/BKREQ command from DSP.

0: This task doesn’t issue WDREQ/BKREQ command. MPU can issue WDSND/BKSND command to this task at any time.

Page 34: Linux DSP Gateway Specification - SourceForge

34 (126)

2.3.3.15. TADD

Task Add. ARM requests to add a new dsptask to DSP with this command. In the TADD request from ARM to DSP, the address of the new dsptask is informed to DSP using System IPBUF. Triggered by this command, DSP appends the new dsptask to the system and configure it, then returns TADD response to ARM with the TID of the new dsptask. If this fails on DSP side, is returns TADD response with TID_ANON (anonymous TID). See 2.4.1.3 for the task add sequence. Direction

ARM to DSP yes (request) DSP to ARM yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 0 0 0 1 0 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x62 command[7:0] TID DSP task ID (only for response from DSP to ARM) data[15:0] don’t care

Data structure sent on the System IPBUF

Word Name Description 0 adrh upper 7 bits 1 adrl lower 16 bits

address of dsptask structure to be added. (word address)

Page 35: Linux DSP Gateway Specification - SourceForge

35 (126)

2.3.3.16. TDEL

Task Delete. ARM requests to delete the dsptask to DSP with this command. Only the tasks which has been added with TADD command can be deleted. Triggered by this command, DSP does away with the dsptask from the system, then returns same command to ARM as the completion notification. See 2.4.1.3 for the task delete sequence. Direction

ARM to DSP yes (request) DSP to ARM yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 0 0 0 1 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register TYPE

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x63 command[7:0] TID DSP task ID data[15:0] MODE TDEL mode

TYPE description

Command MODE Description SAFE 0x00 System waits this task to process all commands registered in the

queue before deleting the task object and resources. KILL 0x01 The task object and resources are deleted immediately.

Page 36: Linux DSP Gateway Specification - SourceForge

36 (126)

2.3.3.17. TSTOP

Task Stop. This command is used only in DSP internally. Direction

ARM to DSP no DSP to ARM no

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register 1 1 0 0 1 0 1 don’t care 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] don’t care command[14:8] CMD_H 0x65 command[7:0] don’t care data[15:0] don’t care

Page 37: Linux DSP Gateway Specification - SourceForge

37 (126)

2.3.3.18. DSPCFG

DSP Configuration Request/Response. ARM requests DSP configuration information by this command, with CFGTYP=REQ. DSP should respond to the request also by this command, along with configuration data in the System Buffer. The response from DSP consists of a sequence of several commands, which are identified with CFGTYP. At the last command of the response sequence, L (Last) bit should be asserted. It also means system configuration data in the System Buffer is ready to be read by ARM. If any error occurred in DSP while initialization, it should respond with CFGTYP=ABORT. It means the DSP binary contains fatal error and needs to be revised. In this case ARM should not send mailbox command to DSP anymore. This command also initializes the ownerships of all IPBUFs. At the default state, DSP owns all IPBUFs. DSP can issue BKYLD commands after DSPCFG command sequence, in order to yield some ownerships to ARM side See 2.4.1.1 for the configuration sequence. Direction

ARM to DSP yes (request) DSP to ARM yes (response)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 0 0 L CFGTYP 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register CFGDATA

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x70 command[7] L end of configuration data indicator

configuration type Code Command Description 0x00 REQ configuration request 0x28 SYSADRH 0x29 SYSADRL

System IPBUF address (word address)

0x70 PROTREV Mailbox Protocol Revision ID

command[6:0] CFGTYP

0x78 ABORT abort response data[15:0] CFGDATA configuration data

Page 38: Linux DSP Gateway Specification - SourceForge

38 (126)

Configuration data structure (on the System Buffer)

Word Name Description 0 task_max maximum task number in DSP. 1 bln Global IPBUF line number. 2 bsz Global IPBUF line size information. (in word count) 3 upper 7 bits 4

badr lower 16 bits

Global IPBUF address. (word address)

5 upper 7 bits 6

sys_da lower 16 bits

The address of the System IPBUF for DSP->ARM. (word address)

7 upper 7 bits 8

sys_ad lower 16 bits

The address of the System IPBUF for ARM->DSP. (word address)

9 upper 7 bits 10

mbseq lower 16 bits

The address of mailbox sequence checker. (word address)

11 upper 7 bits 12

dbg_buf lower 16 bits

The address of debug buffer. (word address)

13 dbg_buf_sz debug buffer size. (in word count) 14 dbg_line_sz Maximum size for one debug message. (in word count) 15 upper 7 bits 16

mem_sync.DARAM lower 16 bits

The address of debug buffer. (word address)

17 upper 7 bits 18

mem_sync.SARAM lower 16 bits

The address of debug buffer. (word address)

19 upper 7 bits 20

mem_sync.SDRAM lower 16 bits

The address of debug buffer. (word address)

♦ CFGTYP = REQ ARM requests DSP configuration with this command.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x70 command[7] L 0 command[6:0] CFGTYP 0x00 data[15:0] don’t care

Page 39: Linux DSP Gateway Specification - SourceForge

39 (126)

♦ CFGTYP = SYSADRH ♦ CFGTYP = SYSADRL System IPBUF address information.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 0 0 L 0 1 0 1 0 0 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register ADR

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x70 command[7] L last data indicator

0x28 SYSADRH: ADR represents upper 7 bits of the System IPBUF address

command[6:0] CFGTYP

0x29 SYSADRL: ADR represents lower 16 bits of the System IPBUF address

data[15:0] ADR address

♦ CFGTYP = PROTREV Mailbox protocol revision information.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 0 0 L 1 1 1 0 0 0 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register REV

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x70 command[7] L last data indicator command[6:0] CFGTYP 0x70 data[15:0] REV Mailbox protocol revision ID

Page 40: Linux DSP Gateway Specification - SourceForge

40 (126)

♦ CFGTYP = ABORT Abort response.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 0 0 L 1 1 1 1 0 0 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x70 command[7] L don’t care command[6:0] CFGTYP 0x78 data[15:0] don’t care

Page 41: Linux DSP Gateway Specification - SourceForge

41 (126)

2.3.3.19. REGRW

Register Read / Write. This command is used to read or write at specified address in DSP memory or I/O space from ARM. Note that the address greater than 0xffff in memory space is not accessible with this command. See 2.4.2.3 for the read / write sequence. Direction

ARM to DSP yes (read, write) DSP to ARM yes (read data)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 0 1 0 TYPE 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register A/D

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x72

command type Code Command Description 0x00 MEMR Memory Read 0x01 MEMW Memory Write 0x02 IOR I/O Read 0x03 IOW I/O Write

command[7:0] TYPE

0x04 DATA Data data[15:0] A/D Address or Data

Page 42: Linux DSP Gateway Specification - SourceForge

42 (126)

2.3.3.20. GETVAR, SETVAR

Get / Set Variable. This command is used to read or write DSP system variable from ARM. The values of the variable are sent through the System IPBUF. See 2.4.2.5 for get / set sequence. Direction

ARM to DSP yes (GETVAR, SETVAR) DSP to ARM yes (GETVAR data)

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 0 1 0 * VARID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register don’t care

Bit Name Description command[15] Q Sequence number

0x74 GETVAR command[14:8] CMD_H 0x75 SETVAR

command[7:0] VARID Variable ID data[15:0] don’t care

Configuration data structure (on the System IPBUF)

Word Name Description 1 : n DATA value(s) of the variable

VARID description

Name VARID Description ICRMASK 0x00 Mask for ICR register when DSP falls in idle mode LOADINFO 0x01 DSP load information (only for GETVAR)

Page 43: Linux DSP Gateway Specification - SourceForge

43 (126)

2.3.3.21. ERR

Direction

ARM to DSP no DSP to ARM yes

Error Information. When DSP received illegal mailbox command, it responds with this command.

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 1 0 0 0 EID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register E_CMD_H E_TID

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x78 command[7:0] EID error ID data[15:8] E_CMD_H CMD_H which caused this error data[7:0] E_TID TID which caused this error

EID description

Name EID Description BADTID 0x10 TID in the mailbox command is not valid BADTCN 0x11 Received a transaction not allowed BADBID 0x20 BID in the mailbox command is not valid BADCNT 0x21 CNT in the mailbox command is not valid NOTLOCKED 0x22 An IPBUF line which has not been locked by DSP was going to

be released STVBUF 0x23 DSP is starving for the IPBUF BADADR 0x24 Address in the mailbox command is not valid (unused) BADTCTL 0x30 Received unrecognized TCTL command BADPARAM 0x50 Bad parameter in the mailbox command FATAL 0x58 Fatal error. This is used within DSP MMU error recovery

process. NOMEM 0xc0 DSP could not allocate memory resource NORES 0xc1 DSP could not allocate other resources IPBFULL 0xc2 No free Global IPBUF WDT 0xd0 Watch dog timer expiration TASKNOTRDY 0xe0 DSP task encountered something not initialized properly TASKBSY 0xe1 Some DSP task resources are busy TASKERR 0xef Other error occurred in the task context BADCFGTYP 0xf0 Received unrecognized CFGTYP in DSPCFG command DEBUG 0xf8 EID for debugging BADSEQ 0xfe Illegal sequence of Q bit in the mailbox command BADCMD 0xff Received unrecognized mailbox command

Page 44: Linux DSP Gateway Specification - SourceForge

44 (126)

2.3.3.22. DBG

Debug. DSP sends a debug message using a dedicated buffer. ARM doesn’t issue this command. Direction

ARM to DSP no DSP to ARM yes

Mailbox registers usage

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Command Register Q 1 1 1 1 0 0 1 TID 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Data Register CNT

Bit Name Description command[15] Q Sequence number command[14:8] CMD_H 0x79 command[7:0] TID DSP task ID data[15:0] CNT Data count

Page 45: Linux DSP Gateway Specification - SourceForge

45 (126)

2.4. Mailbox Command Sequence

Some examples of mailbox command sequence are illustrated in this section. They will help you to understand how the mailbox commands are exchanged between the processors. 2.4.1. Configuration Sequence

2.4.1.1. System Configuration

After DSP program has been loaded, system configuration should be done firstly. The configuration sequence is shown in Figure 2-14.

Figure 2-14: System Configuration Sequence

ARM DSP

DSP issues BKYLD for N times after DSPCFG sequence. Here N is the IPBUF line count that DSP want to give to MPU at initial time.

with configuration data in the System IPBUF

DSPCFG : CFG_PROTREV DSPCFG : CFG_SYSADRH DSPCFG : CFG_SYSADRL with LAST bit asserted

BKYLD

BKYLD

DSPCFG : CFG_REQ

2.4.1.2. Task Configuration

Following the system configuration, all static DSP tasks should be configured. The configuration sequence is shown in Figure 2-15.

Figure 2-15: Task Configuration Sequence

ARM DSP

with task configuration data in the System IPBUF

TCFG (response)

TCFG (request)

Page 46: Linux DSP Gateway Specification - SourceForge

46 (126)

2.4.1.3. Task Add / Delete

On-demand task is added to the system with the TADD command. The sequence is shown in Figure 2-16. After the task has been added, it should be configured with TCFG command. See 2.4.1.2.

Figure 2-16: Task Add Sequence

ARM DSP

with task address in the System IPBUF

with TID

(Will be followed by TCFG sequence)

TADD (response)

TADD (request)

On-demand task is deleted from the system with the sequence shown in Figure 2-17.

Figure 2-17: Task Delete Sequence

ARM DSP

TDEL (response)

TDEL (request)

TCTL:TCLR command is generated internally and

executed by the DSP task

TCTL:TCLR

2.4.2. Data Transfer Sequence

The Data transfer sequences are different for every task types. Each sequence is shown below. About the task type, see 5.4.

Page 47: Linux DSP Gateway Specification - SourceForge

47 (126)

2.4.2.1. ARM to DSP transfer

A word data is sent from ARM to a Passive Word Receiving Task with the sequence shown in Figure 2-18.

Figure 2-18: ARM to DSP Data Transfer Sequence in Passive Word Receiving Task

ARM DSP

WDSND

A word data is sent from ARM to an Active Word Receiving Task with the sequence shown in Figure 2-19.

Figure 2-19: ARM to DSP Data Transfer Sequence in Active Word Receiving Task

ARM DSP

WDSND

WDREQ

A block data is sent from ARM to a Passive Block Receiving Task with the sequence shown in Figure 2-20.

Figure 2-20: ARM to DSP Data Transfer Sequence in Passive Block Receiving Task

ARM DSP

BKYLD (optional)

BKSND

Page 48: Linux DSP Gateway Specification - SourceForge

48 (126)

A block data is sent from ARM to an Active Block Receiving Task with the sequence shown in Figure 2-21.

Figure 2-21: ARM to DSP Data Transfer Sequence in Active Block Receiving Task

ARM DSP

BKYLD (optional)

BKSND / BKSNDP

BKREQ / BKREQP

Page 49: Linux DSP Gateway Specification - SourceForge

49 (126)

2.4.2.2. DSP to ARM transfer

A word data is sent from a Passive Word Sending Task to ARM with the sequence shown in Figure 2-22.

Figure 2-22: DSP to ARM Data Transfer Sequence in Passive Word Sending Task

ARM DSP

WDSND

WDREQ

A word data is sent from an Active Word Sending Task to ARM with the sequence shown in Figure 2-23.

Figure 2-23: DSP to ARM Data Transfer Sequence in Active Word Sending Task

ARM DSP

WDSND

A block data is sent from an Passive Block Sending Task to ARM with the sequence shown in Figure 2-24.

Figure 2-24: DSP to ARM Data Transfer Sequence in Passive Block Sending Task

ARM DSP

BKREQ

BKSND / BKSNDP

BKYLD (optional)

Page 50: Linux DSP Gateway Specification - SourceForge

50 (126)

A block data is sent from an Passive Block Sending Task to ARM with the sequence shown in Figure 2-25.

Figure 2-25: DSP to ARM Data Transfer Sequence in Active Block Sending Task

ARM DSP

BKSND / BKSNDP

BKYLD (optional)

2.4.2.3. TCTL

TCTL sequence is shown in Figure 2-27.

Figure 2-26: TCTL Sequence

ARM DSP with address on

the data register, args in the System

IPBUF (if any).

with return value on the data

register (optional)

TCTL

TCTL

2.4.2.4. REGRW

DSP registers (and any data in memory / IO space) can be read / written with REGRW command. The read sequence is shown in Figure 2-27.

Figure 2-27: DSP Register Read Sequence

ARM DSP with address on

the data register

with read data on the data register

REGRW : MEMR / IOR

REGRW : DATA

Page 51: Linux DSP Gateway Specification - SourceForge

51 (126)

The write sequence is shown in Figure 2-28.

Figure 2-28: DSP Register Write Sequence

ARM DSP with address on the

data register, data in the System IPBUF

REGRW : MEMW / IOW

2.4.2.5. GETVAR / SETVAR

The DSP system parameters can be read / written with GETVAR / SETVAR command. The read sequence is shown in Figure 2-29.

Figure 2-29: DSP System Parameter Read Sequence

ARM DSP

with read data on the System IPBUF GETVAR : VARID

GETVAR : VARID

The write sequence is shown in Figure 2-30.

Figure 2-30: DSP System Parameter Write Sequence

ARM DSP

with set data on the System IPBUF

SETVAR : VARID

Page 52: Linux DSP Gateway Specification - SourceForge

52 (126)

3. LINUX API 3.1. Overview

Figure 3-1: DSP Gateway Linux APIs

DSP ARM(Linux)

Mailbox

“task1” “task2” “task3”

/dev/dsptask/ task1

/dev/dsptask/ task2

/dev/dsptask/ task3

user app.

dspctl utility

/dev/dspctl/ ctl

/dev/dspctl/ m

em

INT handler

DSP Gateway library

DSP memory

device I/F

DSP control

device I/F

DSP task device I/F

DSP Gateway driver

INT handler

DSP/ BIOS TASK

DSP/ BIOS TASK

DSP/ BIOS TASK

task API

DSP task

watch device I/F

/dev/dspctl/ tw

ch

Dynamic Loader Daemon

/dev/dspctl/ err

DSP error

detection device I/F

Figure 3-1 shows Linux APIs for the DSP Gateway driver. There are five device interfaces regarding the DSP Gateway - DSP task devices, DSP task watch device, DSP control device, DSP error detection device and DSP memory device. In general, user applications which want to utilize a DSP task (like an audio / video codec) need to access only to the DSP task devices. Other device I/Fs are used by special utility programs, i.e. DSP application Dynamic Loader Daemon and dspctl utility. 3.2. DSP Task Devices

The DSP task devices provide interfaces to the DSP tasks for Linux applications. Those device files are created automatically by kernel or udevd, or manually by yourself (See 4.3 for details). Also symbolic links will be made at /dev/dsptask directory with the name of the task, by the dspctl utility. (device files)

crw-r--r-- 1 root root 97, 0 Jan 1 0:01 /dev/dsptask0 crw-r--r-- 1 root root 97, 1 Jan 1 0:01 /dev/dsptask1

(symbolic links)

lr-xr-xr-x 1 root root 13 Jan 1 0:01 /dev/dsptask/taskname1 -> /dev/dsptask0 lr-xr-xr-x 1 root root 13 Jan 1 0:01 /dev/dsptask/taskname2 -> /dev/dsptask1

Reading from and writing to those devices mean receiving and sending data from/to the DSP tasks. There are two types of DSP task, static task and on-demand task. The static tasks are linked with the tokliBIOS kernel statically, and are loaded to DSP memory together. They become available by DSP configuration (i.e. DSPCFG ioctl command to the DSP control device), and stay alive until DSP unconfiguration (i.e. DSPUNCFG ioctl command to the DSP control device). Unlike the static tasks, the on-demand tasks are not linked with the tokliBIOS kernel statically but loaded and linked dynamically. To use the on-demand tasks, Linux side needs to create the task device file with MKDEV ioctl command to

Page 53: Linux DSP Gateway Specification - SourceForge

53 (126)

the DSP task watch device (/dev/dspctl/twch), then load the task program object to DSP memory, and issue TADD ioctl command to the DSP task watch device. This series of procedure will be taken care by the DSP Dynamic Loader Daemon. 3.2.1. open()

This driver allows to be opened by two or more processes at same time. In this case, device lock operation might be needed to ensure some exclusive sequence, for instance write then read the result. While one process is locking the dsptask device, all read(), write() and ioctl() calls from other process is blocks until the locking process unlocks the device. Figure 3-2 shows an example of the device lock operation.

Figure 3-2: Example of Device Lock Operation

open()

process1

ioctl(LOCK)

ioctl(UNLOCK)

read()

write()

open()

process2

ioctl(LOCK)

(blocks while process1 is locking the

device)

ioctl(UNLOCK)

read()

write()

close() close()

process1 is locking this device

process2 is locking this device

dsptask device lock status

If this device has been created by MKDEV ioctl (i.e. the DSP task is on-demand type), and the DSP task has not been attached to this device, this open call blocks, and the kernel wakes up the DSP Dynamic Loader Daemon. The daemon loads the corresponding task object and issue TADD ioctl to the DSP control device, then this device gets available and open call is completed.

Page 54: Linux DSP Gateway Specification - SourceForge

54 (126)

3.2.2. close()

If this device has been created by MKDEV ioctl (i.e. the DSP task is on-demand type), the kernel wakes up the DSP Dynamic Loader Daemon in order to inform that this task is not in use any more and resources can be released. 3.2.3. read()

Receives data from the DSP task. For a Passive Sending task, ARM sends a request to DSP and waits for the response from DSP. Until the response comes, the read() blocks (Figure 3-3). For an Active Sending task, read() blocks if the driver hasn’t received any data from DSP until any data comes (Figure 3-4). If DSP has already sent some data to ARM, read() can return immediately (Figure 3-5). DSP task can’t detect the presence of the read-waiting process in Linux side, and just send data arbitrary. The Linux application can detect whether the driver has received data from DSP or not with poll() / select() call. This driver receives read data from DSP only when the device is being opened, even from Active Sending tasks. If any data arrived from the task which is not being opened by any applications, the driver simply discards those data. Application programmer should note that the address of the read buffer, specified as the second argument of the read() system call, should be aligned in 2-byte boundary. This function checks it and if not, returns with an error.

Figure 3-3: read( ) call to Passive Sending Task

ARM DSP

call read( )

read( ) returns

blocking

WDREQ/ BKREQ

WDSND/ BKSND

Figure 3-4: read( ) call to Active Sending Task before DSP data send

Figure 3-5: read( ) call to Active Sending Task after DSP data send

ARM DSP

call read( )

read( ) returns

blocking WDSND/ BKSND

ARM DSP

call read( )read( ) returns

WDSND/ BKSND

Page 55: Linux DSP Gateway Specification - SourceForge

55 (126)

3.2.4. write()

Sends data to the DSP task. For a Passive Receiving task, write() always sends the data to DSP immediately (Figure 3-6). For an Active Receiving task, write() blocks if the driver hasn’t received any data request from DSP (Figure 3-7). If there is a pending request from DSP, write() can send the data to DSP immediately (Figure 3-8). A DSP task can’t detect the presence of write-waiting processes in Linux side, but just issues data requests arbitrarily. The Linux application can detect whether the driver has pending request from DSP or not with poll() / select() call. Application programmer should note that the address of the write data, specified as the second argument of the write() system call, should be aligned in 2-byte boundary. This function checks it and if not, returns with an error.

Figure 3-6: write( ) call to Passive Receiving Task

ARM DSP

call write( )

write( ) returns

WDSND/ BKSND

♦ Active Receiving Task

Figure 3-7: write( ) call to Active Receiving Task before DSP data request

Figure 3-8: write( ) call to Active Receiving Task after DSP data request

write () before DSP data request

write() after DSP data request

ARM DSP

call write( )

write( ) returns

blocking WDREQ/ BKREQ

WDSND/ BKSND

ARM DSP

call write( )

write ( ) returns

WDREQ/ BKREQ

WDSND/ BKSND

3.2.5. poll(), select()

Sees if you can do non-blocking read/write for the DSP task. These calls have a meaning only for the input check for Active Sending tasks or output check for Active Receiving tasks. When poll() or select() are used for the input check for a Passive Sending task or the output check for a Passive Receiving task, it will always be set and returns immediately.

Page 56: Linux DSP Gateway Specification - SourceForge

56 (126)

3.2.6. ioctl()

Basically, ioctl() commands are forwarded to the DSP task as TCTL mailbox commands (See 2.3.3.8. for TCTL command). The user can define ioctl/TCTL commands in the range of 0x8000 – 0x81ff and 0x9000 – 91ff. Additionally, the command range of 0x80 – 0xff is also user defined, but it is kept for backward compatibility. The user should not define any commands in this range newly. Ioctl commands above 0x10000 are not related to TCTL.

Table 3-1: DSP Task Device ioctl( ) Commands

ioctl command Description 0x0000 -0x007f Issues TCTL to the DSP task. (commands are reserved for system)

0x0000 Reserved. 0x0001 TEN Issues TCTL:TEN to DSP. 0x0002 TDIS Issues TCTL:TDIS to DSP. 0x0003 Reserved. 0x0004 Reserved.

others Reserved. 0x0080 - 0x00ff Issues TCTL to the DSP task. (no parameter, no return value)

This range is kept for backward compatibility. DO NOT define new commands in this range.

0x0100 – 0x7fff Reserved. 0x8000 – 0x80ff Issues TCTL to the DSP task. (no parameter, no return value) 0x8100 – 0x81ff Issues TCTL to the DSP task. (1 parameter, no return value) 0x8200 – 0x8fff Reserved. 0x9000 – 0x90ff Issues TCTL to the DSP task. (no parameter, have a return value) 0x9100 – 0x91ff Issues TCTL to the DSP task. (1 parameter, have a return value) 0x9200 – 0xffff Reserved.

0x10000 - Commands in this range are not related to TCTL. 0x10000 BFLUSH Flushes receive buffer. 0x10001 SETBSZ Changes receive buffer size.

Same thing can be done by writing to /sys/devices/platform/dsp/dsptask<n>/fifosz.

0x10002 LOCK Acquire device lock. 0x10003 UNLOCK Release device lock. 0x10004 GETNAME Acquire device name.

others Reserved. 3.2.7. mmap()

Shares the memory block exported from the DSP task. This is valid only for the DSP task which has mmap_info structure (see 5.5). After mmapping, the application can access to the task memory block (which starts from mmap_info.start) directly. It should be noted that the data path using mmap() is totally independent from read() or write(). It means that the data obtained by read() and copied from the mmapped buffer will be different. The data synchronization between ARM and DSP can be carried out with read() and write(). For example, after ARM application writes data to the mmapped buffer, it writes the information of the written data – i.e. offset address in the shared buffer and data size. An example is shown in List 3-1 and List 3-2.

Page 57: Linux DSP Gateway Specification - SourceForge

57 (126)

List 3-1: mmap example – ARM side List 3-2: mmap example – DSP side unsigned long cmdbuf[2]; addr = mmap(NULL, maplen, PROT_READ | PROT_WRITE, MAP_SHARED, dsp_fd, 0)); memcpy(addr, userdata, wordsize); cmdbuf[0] = 0; // offset cmdbuf[1] = wordsize; // length write(dsp_fd, cmdbuf, 8);

static struct mmap_info mmap_info = { shmem, // start 0x1000 // length }; Uns mm_rcv_bksnd(struct dsptask *task, Uns bid, Uns cnt) { Uns *adr; Uns *ipbp = ipbuf_d[bid] off = ((LgUns)ipbp[1] << 16) | ipbp[0]; len = ((LgUns)ipbp[3] << 16) | ipbp[2]; unuse_ipbuf(task, bid); adr = shmem + off; /*

* handle data at adr... */ }

3.3. DSP Control Device

The DSP control device provides DSP control API for Linux. Linux applications can control DSP reset, read DSP configuration, and perform other various controls through this device. In devfs system, the device file /dev/dspctl/ctl will be created automatically. Otherwise, the user needs to create the device file with ‘mknod /dev/dspctl/ctl c 96 0’.

crw-r--r-- 1 root root 96, 0 Jan 1 0:00 /dev/dspctl/ctl 3.3.1. ioctl()

Following ioctl commands are defined. (GBL_IDLE, CPU_IDLE, MPUI_WORDSWAP_ON/OFF, MPUI_BYTESWAP_ON/OFF are only supported for OMAP1 architecture) ♦ RESET ♦ RUN

Resets DSP or releases the reset.

♦ SETRSTVECT

Sets specified address for the DSP reset vector.

♦ GBL_IDLE (only for OMAP1) ♦ CPU_IDLE (only for OMAP1)

Let DSP in the idle state by executing short program in DSP. GBL_IDLE command brings DSP into the global idle state, and it results the IDLE_DSP bit (bit 6) in the ARM_SYSST register to be set and the MPUI to be HOM (Host Only Mode). On the other hand, CPU_IDLE command brings DSP into the CPU idle state, and keep MPUI in SAM (Shared Access Mode). The ICR register is set according to the icrmask value and can be controlled through SETVAR ioctl or

Page 58: Linux DSP Gateway Specification - SourceForge

58 (126)

/sys/devices/platform/dsp/icrmask entry, though the DPLL and DMA domains will not be idled regardless of the icrmask value.

♦ MPUI_WORDSWAP_ON (only for OMAP1) ♦ MPUI_WORDSWAP_OFF (only for OMAP1)

Turns on / off the wordswap in MPUI block. It affects the accesses to DARAM/SARAM from ARM.

♦ MPUI_BYTESWAP_ON (only for OMAP1) ♦ MPUI_BYTESWAP_OFF (only for OMAP1)

Turns on / off the byteswap in MPUI block. It affects the accesses to DARAM/SARAM from ARM.

♦ DSPCFG

Obtains DSP system/task information and creates the DSP task device files. (The devices created by this ioctl command are static tasks.)

♦ DSPUNCFG

Deletes the DSP task device files and kernel internal structures regarding those tasks.

♦ TASKCNT

Obtains the number of static dsp tasks.

♦ REGMEMR ♦ REGMEMW ♦ REGIOR ♦ REGIOW

Read from / writes to DSP memory or I/O space by issuing REGRW mailbox command to DSP. This command takes an argument, the pointer of struct omapdsp_reginfo.

struct omapdsp_reginfo { unsigned short adr; unsigned short val[5]; }

adr Address in question val Value: user should set when write, result will be here when read

♦ GETVAR ♦ SETVAR

Get or set DSP system variable by issuing GETVAR / SETVAR mailbox command to DSP. This command takes an argument, the pointer of struct omapdsp_varinfo.

struct omapdsp_varinfo { unsigned char varid; unsigned short val; }

varid ID of the system variable (see 2.3.3.20). val Value: user should set when write, result will be here when read

♦ RUNLEVEL

Switches DSP system runlevel by issuing RUNLEVEL mailbox command to DSP. See 2.3.3.11 for more detail about RUNLEVEL mailbox command.

Page 59: Linux DSP Gateway Specification - SourceForge

59 (126)

♦ SUSPEND ♦ RESUME

SUSPEND sends SUSPEND mailbox command to DSP and waits for the SUSPEND response. After that, resets DSP. RESUME releases DSP reset. (almost same with RUN ioctl)

♦ MBSEND (for debug use)

Sends mailbox command to the DSP manually. This command takes an argument, the pointer of struct omapdsp_mailbox_cmd.

3.4. DSP Memory Device

The DSP memory device provides the access to the DSP memory space for the DSP program loader in Linux side. In devfs system, the device file /dev/dspctl/mem will be created automatically. Otherwise, the user need to create the device file with ‘mknod /dev/dspctl/mem c 96 1’.

crw-r--r-- 1 root root 96, 1 Jan 1 0:00 /dev/dspctl/mem The DSP program loader loads the DSP binary image to the DSP internal memories (i.e. DARAM and SARAM) through this device. Moreover, the user can extend the usable DSP memory range by mapping external SDRAM block to the DSP memory space using ioctl commands to this device. After mapping, the DSP application loader can access to the extended memory as well.

Figure 3-9: External Memory Mapping for DSP Space 00_0000

01_0000DARAM SARAM

02_8000

DSP MEMORY SPACE FF_FFFF

The extended memory area

3.4.1. lseek()

Seeks in the DSP external memory space. 3.4.2. read()

Reads data from the DSP external memory space. This can be used for the debug purpose.

Page 60: Linux DSP Gateway Specification - SourceForge

60 (126)

3.4.3. write()

Writes data to the DSP external memory space. 3.4.4. ioctl()

Following ioctl commands are defined. They are used to maintain DSP memory mapping through the DSP MMU. ♦ MMUINIT (for debug use)

Initializes DSP MMU unit. Usually it is done automatically.

♦ EXMAP

Allocates the buffer and maps it to the DSP memory space by registering an entry in DSP MMU TLB and also to Linux virtual space by setting page table entry. Programmer can extend available memory for DSP (Figure 3-10). This buffers can be accessed through the DSP exmem device driver. This command takes an argument, the pointer of struct omapdsp_mapinfo.

struct omapdsp_mapinfo { unsigned long dspadr; unsigned long size; }

adr Address to which the allocated buffer will be mapped in the DSP space val Required size

Figure 3-10: DSP Memory Expansion with EXMAP ioctl

00_0000

01_0000DARAM SARAM

02_8000

DSP MEMORY SPACE FF_FFFF

00_0000

01_0000DARAM SARAM

02_8000

FF_FFFF

dspadrsize

♦ EXUNMAP

Releases one buffer allocated by EXMAP ioctl and flushes corresponding mappings in the DSP MMU TLB and Linux page table. This command takes an argument, the DSP address which has been set to dspadr entry in struct omapdsp_mapinfo at the EXMAP ioctl.

♦ EXMAP_FLUSH

Releases all buffers allocated by EXMAP ioctl and flushes corresponding mappings in the DSP MMU TLB and Linux page table. It doesn’t flushes the mapping for interrupt vectors.

Page 61: Linux DSP Gateway Specification - SourceForge

61 (126)

Figure 3-11: Clear of External Memory Mapping from DSP space with EXMAP_FLUSH ioctl 00_0000

01_0000DARAM SARAM

02_8000

DSP MEMORY SPACE FF_FFFF

00_0000

01_0000DARAM SARAM

02_8000

FF_FFFF

Areas mapped by EXMAP ioctl

♦ FBEXPORT

Maps the framebuffer to the DSP memory space and to corresponding Linux virtual space. By doing this, DSP can access to frame buffer directly, without sending back the image data to ARM. This can help to increase the performance of image decoders. This command takes an argument, the pointer of the dspadr variable. The application sets a hint address on this variable, then the DSP Gateway driver returns actual mapped address on it.

♦ MMUITACK

When the application (DSP Dynamic Loader daemon etc.) has detected the DSP MMU error, it issues this ioctl in order to acknowledge the error and switch the DSP to the RECOVERY runlevel.

♦ KMEM_RESERVE ♦ KMEM_RELEASE

Reserves or releases kernel memory blocks in the internal pool, for the future EXMAP. With the Linux memory management, once the kernel memory pages are fragmented, it is difficult to allocate large buffers (ex. 1MB) for EXMAP, even just after EXUNMAP the same size of buffer. To avoid this situation (EXMAP failure), the user can reserve needed size of buffer while the memory is not fragmented, i.e. within or just after the system booting process. Once some memory blocks are reserved with KMEM_RESERVE, they are secured for DSP however many times EXMAP and EXUNMAP are repeated, until they will be released with KMEM_RELEASE.

Figure 3-12: KMEM_RESERVE and KMEM_RELEASE

Kernel Memory

KMEM_RESERVE

KMEM_RERELASE

Internal Buffer Pool

1MB block

64kB block

EXMAP

EXUNMAP

DSP Memory

Page 62: Linux DSP Gateway Specification - SourceForge

62 (126)

3.5. DSP Task Watch Device

The DSP Task Watch device provides functionalities needed for the DSP Dynamic Loader Daemon. In devfs system, the device file /dev/dspctl/twch will be created automatically. Otherwise, the user need to create the device file with ‘mknod /dev/dspctl/twch c 96 2’.

crw-r--r-- 1 root root 96, 2 Jan 1 0:00 /dev/dspctl/twch The daemon can obtain the information which task is in use, not in use or requesting to be loaded and started. It adds and deletes on-demand DSP tasks, creates and removes DSP task device files for those tasks through the ioctl() commands for this device. 3.5.1. read()

Reads status of DSP task devices. The read data is byte-stream and each 4 bytes represents one device status (Table 3-2). The data by each read() call always starts from the status of minor number 0 device. For example, if you read 10 * 4 bytes from DSP Task Watch device, you get statuses of minor number 0 to 9 devices.

Table 3-2: Fields in the Data read from DSP Task Watch Device

Byte Description [0:3] open status of task device of minor number 0 [4:7] open status of task device of minor number 1 [8:11] open status of task device of minor number 2 : :

The meanings of open status value are shown in Table 3-3.

Table 3-3: Value Definition of the Data read from DSP Task Watch Device

Status Name Value Description

NOTASK 0x00000001 DSP task is not attached to this device. Initial state for on-demand task.

ATTACHED 0x00000002 DSP task is attached to this device. Static tasks are always in this state.

GARBAGE 0x00000004 Garbage. The DSP task is killed and the device is waiting to be closed by all application processes.

INVALID 0x00000008 Invalid. This device can not be used anymore and waiting to be removed.

ADDREQ 0x00000100 An application process has opened this on-demand device and the DSP task has not been added yet. When the Dynamic Loader Daemon observes this state, it should load the dynamic task object to the DSP memory and issue TADD ioctl to the Task Watch device.

DELREQ 0x00000200 All application processes have closed this on-demand device and the DSP task has not been deleted yet. When the Dynamic Loader Daemon observes this state, it should issue TDEL ioctl to the Task Watch device.

ADDFAIL 0x00001000 TADD ioctl has failed. Waiting for the open() function which has caused this TADD process to be finished.

ADDING 0x00010000 ADDREQ state is acknowledged by the Dynamic Loader Daemon, and TADD process is on-going.

Page 63: Linux DSP Gateway Specification - SourceForge

63 (126)

DELING 0x00020000 DELREQ state is acknowledged by the Dynamic Loader Daemon, and TDEL process is on-going.

KILLING 0x00040000 Someone has issued TKILL ioctl to the Task Watch device and the process is on-going.

The open status values correspond to the static tasks are always seen as ATTACHED. The read() call will block if no task has changed their open status since previous read(), until any status changes occur. If the user process should not block, it should call poll() or select() before calling read(). 3.5.2. poll(), select()

Sees if the user process can do non-blocking read for the DSP Task Watch device. 3.5.3. ioctl()

Following ioctl commands are defined for on-demand DSP task creation and removal. ♦ MKDEV ♦ RMDEV

Creates / removes a DSP task device file. It will become the stub device for the on-demand task added by TADD ioctl in future.

♦ TADD

Adds on-demand task by issuing TADD mailbox command to DSP. The new task will be attached to the task device of same name with this DSP task. The corresponding task device should be created beforehand by MKDEV ioctl. This command takes an argument, the pointer of struct omapdsp_taddinfo.

struct omapdsp_taddinfo { unsigned long minor; unsigned long taskadr; }

minor minor device number of the task device. taskadr address of the dsptask structure of newly adding task.

♦ TDEL

Detaches the on-demand task from the task device and disable that task in DSP side by issuing TDEL:SAFE mailbox command. The task device remains until being deleted explicitly by RMDEV ioctl.

♦ TKILL

Detaches the on-demand task from the task device and disable that task in DSP side by issuing TDEL:KILL mailbox command. TDEL:KILL command will not wait for the DSP task to finish all commands registered its queue, unlike TDEL:SAFE command. The task device remains until being deleted explicitly by RMDEV ioctl.

Page 64: Linux DSP Gateway Specification - SourceForge

64 (126)

3.6. DSP Error Detection Device

The DSP Error Detection device is used to detect error from DSP, such as watchdog timer expiration and DSP MMU error interrupt. In devfs system, the device file /dev/dspctl/err will be created automatically. Otherwise, the user need to create the device file with ‘mknod /dev/dspctl/err c 96 3’.

crw-r--r-- 1 root root 96, 3 Jan 1 0:00 /dev/dspctl/err 3.6.1. read()

Reads a 32-bit error code. The read() call blocks until any of DSP errors listed in Table 3-4 occurs. Table 3-4: Error Code

Bit name Short Description 31:2 reserved 1 MMU MMU fault 0 WDT WDT expiration

♦ MMU

Received a DSP MMU interrupt.

♦ WDT

DSP watchdog timer has been expired.

3.6.2. poll(), select()

Sees if any errors are detected and read() can be done without blocking. 3.7. sysfs Entries for Setting / Getting Status

Several sysfs entries are created for status checks, parameter checks and changes. Those entries are located under /sys/devices/platform/dsp. 3.7.1. cpustat

Read-only entry. This shows the current DSP CPU state.

List 3-3: cpustat example # cat /sys/devices/platform/dsp/cpustat run

3.7.2. mblog

Read-only entry. This shows the log of mailbox command exchanges. It will be helpful for debugging.

List 3-4: mblog example # cat /sys/devices/platform/dsp/mblog

Page 65: Linux DSP Gateway Specification - SourceForge

65 (126)

log count:86 / ARM->DSP:43, DSP->ARM:43 ARM->DSP ARM<-DSP jiffies q cmd data q cmd data 0000173d 0 3004 0000 TCTL:task 4 0000173e 1 e005 0000 TCFG:task 5 0000173e 0 e005 0000 TCFG:task 5 0000173f 0 3005 0000 TCTL:task 5 00001740 1 e006 0000 TCFG:task 6 : 00001f56 1 2001 0001 BKSND:task 1 00001f56 0 2300 0005 BKYLD 00001fba 0 f901 0000 DBG 00001fba 1 2001 0002 BKSND:task 1 00001fba 1 2300 0006 BKYLD

3.7.3. ifver

Read entry. This shows supported interface version. This would be checked by the utility tools.

List 3-5: ifver example # cat /sys/devices/platform/dsp/ifver 3.2 3.3

3.7.4. icrmask

Read and write entry. This is the mask value of ICR register in DSP. This value affects when DSP falls in idle mode.

List 3-6: icrmask example # cat /sys/devices/platform/dsp/icrmask 0xffff # echo 0 > /sys/devices/platform/dsp/icrmask # cat /sys/devices/platform/dsp/icrmask 0x0000

3.7.5. mempool

Read entry. This is the current status of the kernel memory pool for exmap. It contains three fields as shown in List 3-7: The first field shows the total memory size reserved in the pool. The second and third fields show buffer block counts reserved in the 1MB pool and 64KB pool respectively.

List 3-7: mempool example # cat /sys/devices/platform/dsp/mempool 0x360000 1M buffer: 3(0 free) 64K buffer: 0(0 free)

Page 66: Linux DSP Gateway Specification - SourceForge

66 (126)

3.7.6. mmu

Read entry. This shows DSP MMU TLB status.

List 3-8: mmu example # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 02: P V 4KB 0xfe2000 0x48094000 L 32 03: P V 4KB 0xfdc000 0x4807c000 L 32 04: P V 4KB 0xfdd000 0x4807e000 L 32 05: P V 4KB 0xfde000 0x48080000 L 32 06: P V 4KB 0xfdf000 0x48082000 L 32 07: V 4KB 0x028000 0x84fc0000 L 16 lock base = 8 victim = 8 08: V 4KB 0x029000 0x84f1f000 L 16 09: 64KB 0x030000 0x87700000 L 16 10: 1MB 0x000000 0x00000000 L 8 : 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8

3.7.7. ipbuf

Read entry. This shows Global IPBUF status. This entry will be accessible only when DSP is running.

List 3-9: ipbuf example # cat /sys/devices/platform/dsp/ipbuf ipbuf[0]: adr = 0xe0100000 DSPtask[1]->Linux (already read and now free for Linux) ipbuf[1]: adr = 0xe010c00c DSPtask[1]->Linux (already read and now free for Linux) ipbuf[2]: adr = 0xe0118018 Linux->DSPtask[254] (already read and now free for DSP) ipbuf[3]: adr = 0xe0124024 Linux->DSPtask[254] (already read and now free for DSP) ipbuf[4]: adr = 0xe0130030 Linux->DSPtask[254] (already read and now free for DSP) ipbuf[5]: adr = 0xe013c03c Linux->DSPtask[254] (already read and now free for DSP) ipbuf[6]: adr = 0xe0148048 DSPtask[1]->Linux (already read and now free for Linux) ipbuf[7]: adr = 0xe0154054 DSPtask[1]->Linux (already read and now free for Linux) Free IPBUF link: 6 7 0 1 IPBFULL error count: 0

Page 67: Linux DSP Gateway Specification - SourceForge

67 (126)

3.7.8. loadinfo

Read entry. This shows DSP load information. This entry will be accessible only when DSP is running.

List 3-10: loadinfo example # cat /sys/devices/platform/dsp/loadinfo DSP load info: 10ms average = 0.13% 1sec average = 0.13% busiest 10ms = 0.34% 1min average = 0.13% busiest 1s = 0.13%

3.7.9. exmap Read entry. This shows information about mapped external memory in DSP.

List 3-11: exmap example # dspctl exmap 0x100000 100000 mapping external memory for DSP: dspadr = 0x100000, size = 0x100000 1048576 (0x100000) bytes mapped. # dspctl exmap 0x100000 100000 # cat /sys/devices/platform/dsp/exmap dspadr size buf size uc 0xfff000 0x1000 0xc7d70000 0x1000 0 : 0xfdf000 0x1000 0x 0 0x1000 0 0x100000 0x100000 0xc4800000 0x100000 0

3.7.10. <dsptask[0-9]+>/devname

Read entry. This shows the DSP taskdev name. (In most cases, same with DSP task name.)

List 3-12: <dsptask[0-9]+>/devname example # cat /sys/devices/platform/dsp/dsptask0/devname hellotimer

3.7.11. <dsptask[0-9]+>/devstate

Read entry. This shows the state of the DSP taskdev state machine.

List 3-13: <dsptask[0-9]+>/devstate example # cat /sys/devices/platform/dsp/dsptask0/devstate attached

Page 68: Linux DSP Gateway Specification - SourceForge

68 (126)

3.7.12. <dsptask[0-9]+>/taskname

Read entry. This shows the DSP task name.

List 3-14: <dsptask[0-9]+>/taskname example # cat /sys/devices/platform/dsp/dsptask0/taskname hellotimer

3.7.13. <dsptask[0-9]+>/ttyp

Read entry. This shows the DSP task type.

List 3-15: <dsptask[0-9]+>/ttyp example # cat /sys/devices/platform/dsp/dsptask0/ttyp 0x000a active global block send passive word receive

3.7.14. <dsptask[0-9]+>/fifosz

Read and write entry. This is the ARM-side receive buffer size of this task. A word sending task has this entry.

List 3-16: <dsptask[0-9]+>/fifosz example # cat /sys/devices/platform/dsp/dsptask0/fifosz 32 # echo 128 > /sys/devices/platform/dsp/dsptask0/fifosz # cat /sys/devices/platform/dsp/dsptask0/fifosz 128

3.7.15. <dsptask[0-9]+>/fifocnt

Read entry. This is the data count in the ARM-side receive buffer. A word sending task has this entry.

List 3-17: <dsptask[0-9]+>/fifocnt example # cat /sys/devices/platform/dsp/dsptask0/fifocnt 0

3.7.16. <dsptask[0-9]+>/ipblink

Read entry. This shows the IPBLINK status of the DSP task. A global block sending task has this entry.

List 3-18: <dsptask[0-9]+>/ipblink example # cat /sys/devices/platform/dsp/dsptask0/ipblink top NULL tail NULL

Page 69: Linux DSP Gateway Specification - SourceForge

69 (126)

3.7.17. <dsptask[0-9]+>/wsz

Read entry. This is the ARM-side write capability to this task.

List 3-19: <dsptask[0-9]+>/wsz example # cat /sys/devices/platform/dsp/dsptask0/wsz 2

3.7.18. <dsptask[0-9]+>/proc_list

Read entry. This shows the list of processes which is using this device.

List 3-20: <dsptask[0-9]+>/proc_list example # cat /sys/devices/platform/dsp/dsptask0/proc_list 176 177

3.8. Header for Applications

Followings are defined in include/omap_dsp.h (See changes from DSPGateway 3.3 in [2]). If applications need to refer to following values and definitions, this header should be included. ♦ error cause definitions for error detection devices ♦ value definitions of task device open status ♦ mailbox protocol definitions ♦ ioctl commands for each device I/F ♦ structure for specific ioctls (omapdsp_reginfo, omapdsp_mapinfo, etc.)

Page 70: Linux DSP Gateway Specification - SourceForge

70 (126)

4. LINUX DRIVER OVERVIEW AND SYSTEM CONFIGURATION

4.1. Overview

The DSP Gateway driver has five device I/Fs (task device I/Fs, task watch device I/F, control device I/F, error detection device I/F and memory device I/F) and two interrupt handlers (Mailbox and DSP MMU), as shown in Figure 4-1.

Figure 4-1: DSP Gateway Driver Block Chart

DSP

ARM(Linux)

DSP memory device I/F

DSP control device I/F

DSP task device I/Fs

Mailbox interrupt handler

DSP task watch device

I/F

Mailbox

open( ) release( )

read( ) write( ) poll( ) ioctl( )

read( ) poll( ) ioctl( )

open( ) release( )

ioctl( )

open( ) llseek( ) read( ) write( ) ioctl( )

WDSND WDREQ BKSND BKREQ

BKSNDP BKREQP

TCFG

WDT

TADD TDEL

DSPCFG REGRW GETVAR SETVAR

DSP MMU

DSP MMU interrupt handler

DSP error detection device I/F read( ) poll( )

BKYLD ERR DBG

4.2. Kernel Configuration

In order to use the DSP Gateway, you should follow the kernel configuration guideline as below. ♦ Enable “System Type ---> TI OMAP Implementations ---> OMAP DSP Driver (DSP Gateway)” (can

be a kernel module) ♦ “Mailbox Command Verbose LOG” is optional, but it will help for debugging. ♦ Enable “DSP Task Multiopen Capability” if you want. ♦ Enable “Framebuffer export to DSP” if you want to access framebuffer from DSP.

Figure 4-2: Kernel Configuration Menu

Page 71: Linux DSP Gateway Specification - SourceForge

71 (126)

4.3. Device Files

DSP Gateway uses the following devices and directories. In some cases they can be created by the kernel or the daemon automatically, otherwise the user should create them manually. Control devices

crw-cw---- 1 root root 96, 0 Jan 1 0:00 /dev/dspctl/ctl crw-r----- 1 root root 96, 1 Jan 1 0:00 /dev/dspctl/mem crw-r----- 1 root root 96, 2 Jan 1 0:00 /dev/dspctl/twch cr--r----- 1 root root 96, 3 Jan 1 0:00 /dev/dspctl/err

Task devices

crw-rw-rw- 1 root root 97, 0 Jan 1 0:00 /dev/dsptask0 crw-rw-rw- 1 root root 97, 1 Jan 1 0:00 /dev/dsptask1 crw-rw-rw- 1 root root 97, 2 Jan 1 0:00 /dev/dsptask2 crw-rw-rw- 1 root root 97, 3 Jan 1 0:00 /dev/dsptask3 crw-rw-rw- 1 root root 97, 4 Jan 1 0:00 /dev/dsptask4 :

Task device directory

drw-rw-rw- 1 root root 4096 Jan 1 0:00 /dev/dsptask/ 4.3.1. udev

An udevd daemon takes care creating and removing all device files, as long as the config files are set up properly. List 4-1 shows an example description regarding DSP devices in udev.rules. This file is typically located at /etc/udev/rules.d/ and the name could be <nn>-udev.rules, where <nn> is a two-digits number like “50-udev.rules”.

Page 72: Linux DSP Gateway Specification - SourceForge

72 (126)

List 4-1: udev.rules example : # DSP devices KERNEL=="dspctl", NAME="dspctl/ctl" KERNEL=="dspmem", NAME="dspctl/mem", MODE="0640", GROUP="kmem" KERNEL=="dsptwch", NAME="dspctl/twch", MODE="0640" KERNEL=="dsperr", NAME="dspctl/err", MODE="0440" KERNEL=="dsptask[0-9]*", MODE="0666" :

The permissions and ownership of the created device could be set from the udev permission files. List 4-2 shows an example description regarding DSP devices in udev.permissions. This file is typically located at /etc/udev/permissions.d/ and the name could be <nn>-udev.permissions, where <nn> is a two-digits number like “50-udev.permissions”. Note: If your permissions file has “dsp*” entry (for audio device, like “dsp*:root:root:0660”), the entries for DSP Gateway should be written before that “dsp*” entry, or it should be re-written as “dsp[0-9]*”. Otherwise that entry will match with all DSP Gateway devices and they will not be set the permissions as expected.

List 4-2: udev.permissions example : # DSP devices dspctl/ctl:root:root:0660 dspctl/mem:root:root:0640 dspctl/twch:root:root:0640 dspctl/err:root:root:0440 dsptask[0-9]*:root:root:0666 : # audio devices dsp*:root:root:0660 :

4.3.2. Manual Setup

If you use neither devfs nor udevd, you need to add the Control devices (/dev/dsptask/*), the Task devices (/dev/dsptask*) and the Task device directory (/dev/dsptask/) by yourself. You can make the task devices as many as you need, but no more than 254 devices.

Page 73: Linux DSP Gateway Specification - SourceForge

73 (126)

5. DSP PROGRAMMING 5.1. Overview

Figure 5-1: DSP Software Block Chart

DSP

ARM(Linux)

Mailbox

“task1”

“task2” “task3”

/dev/dsptask /task1

user application

INT handler DSP system kernel (tokliBIOS)

DSP Gateway Driver

DSP/BIOS TSK (user task)

DSP/BIOS TSK (user task)

DSP/BIOS TSK (user task)

task API

rcv_snd( ) function

queue

DSP/BIOS TSK (supertask)

rcv_req( ) function

rcv_tctl( ) function

Figure 5-1 shows the DSP Software Block Chart. When a Linux user application accesses to the DSP task device, /dev/dsptask/task1 for example, the driver generates a Mailbox command to DSP. In DSP side, the system kernel -- called tokliBIOS -- receives the Mailbox command and registers it into the queue of the corresponding DSP/BIOS TSK. The DSP/BIOS TSK processes the commands in the queue by calling corresponding task function, which is a member of the task1 in this case. This task function is the program which DSP application programmer should implement. The task functions can send back Mailbox commands to ARM by calling task API functions in the tokliBIOS. 5.2. Toolchain

TI provides a tool called CCS (Code Compose Studio) as an environment for C55x software development, and of course it can be used for DSP Gateway. Moreover, since 2004, TI has started to provide the LDT (linux dsp tools) [4], which is a very suitable tool for our purpose. However, unfortunately it doesn’t support OMAP2 devices. More details about these toolchain and the build processes for both tools are described in [1]. 5.3. DSP Task Programming

DSP programmer should implement following functions and data defined in the dsptask structure for each task. Details of those members of the structure are described in 5.5. How to update your DSP Gateway 3.3 DSP task to 3.3.1 is instructed in [2].

Page 74: Linux DSP Gateway Specification - SourceForge

74 (126)

struct dsptask { Uns tid; String name; Uns ttyp; Uns (*rcv_snd)(); /* (*rcv_wdsnd)(struct dsptask *task, Uns data); */ /* (*rcv_bksnd)(struct dsptask *task, Uns bid, Uns cnt); */ /* (*rcv_bksndp)(struct dsptask *task); */ Uns (*rcv_req)(); /* (*rcv_wdreq)(struct dsptask *task); */ /* (*rcv_bkreq)(struct dsptask *task, Uns cnt); */ Uns (*rcv_tctl)(); /* (*rcv_tctl)(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg); */ struct TSK_Attrs *tsk_attrs; struct mmap_info *mmap_info; Void *udata; };

The maximum number of the DSP task is 126 (TID 0x00–0xfd), leaving 0xfe and 0xff for the special purposes for the IPBUF owner information. Note that this dsptask object should be placed in ‘dspgw_task’ section using ‘#pragma DATA_SECTION()’ directive. See List 5-1 for a dsptask instance.

List 5-1: dsptask instance #pragma DATA_SECTION(task_demo_console, "dspgw_task") struct dsptask task_demo_console = { TID_MAGIC, /* tid */ "demo_console", /* name */ MBCMD_TTYP_WDDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active word snd, passive word rcv */ demo_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ NULL /* udata */ };

5.4. Task Type

The DSP task type defines how the task performs the data transmission with ARM. it is defined with a combination of the following options. 5.4.1. Active Sending / Passive Sending

♦ Active Sending task

This task sends WDSND / BKSND / BKSNDP commands spontaneously, without receiving WDREQ/BKREQ/BKREQP command from ARM. If this task received WDREQ / BKREQ / BKREQP command, it returns ERR:BADTCN command.

♦ Passive Sending task

This task sends WDSND / BKSND / BKSNDP commands only in response to the WDREQ / BKREQ / BKREQP command from ARM.

Page 75: Linux DSP Gateway Specification - SourceForge

75 (126)

5.4.2. Active Receiving / Passive Receiving

♦ Active Receiving task

This task issues WDREQ / BKREQ / BKREQP commands to ARM when it needs data. ARM should not send WDSND / BKSND / BKSNDP command to this task unless receiving a request.

♦ Passive Receiving task

This task never issues WDREQ / BKREQ commands to ARM. ARM can send WDSND / BKSND command at any time. Passive Receiving with Private IPBUF is not allowed.

5.4.3. Word Sending / Block Sending

♦ Word Sending task

This task uses WDSND command and never uses BKSND / BKSNDP command to send data to ARM.

♦ Block Sending task

This task uses BKSND / BKSNDP command and never uses WDSND to send data to ARM.

5.4.4. Word Receiving / Block Receiving

♦ Word Receiving task

This task accepts WDSND command to receive data from ARM. If this task received BKSND / BKSNDP command, it returns ERR:BADTCN command to ARM.

♦ Block Receiving task

This task accepts BKSND / BKSNDP command to receive data from ARM. If this task received WDSND command, it returns ERR:BADTCN command to ARM.

5.4.5. Global Block Sending / Private Block Sending

This option is applied only for Block Sending task. ♦ Global Block Sending task

This task uses BKSND command and never uses BKSNDP command to send data to ARM.

♦ Private Block Sending task

This task uses BKSNDP command and never uses BKSND to send data to ARM.

5.4.6. Global Block Receiving / Private Block Receiving

This option is applied only for Block Receiving task.

Page 76: Linux DSP Gateway Specification - SourceForge

76 (126)

♦ Global Block Receiving task

This task accepts BKSND command to receive data from ARM. If this task received BKSNDP command, it returns ERR:BADTCN command to ARM.

♦ Private Block Receiving task

This task accepts BKSNDP command to receive data from ARM. If this task received BKSND command, it returns ERR:BADTCN command to ARM.

5.5. Dsptask structure members

The following instructs how to implement the dsptask structure members. Uns tid

Task ID. The initial value should be TID_MAGIC. The tokliBIOS kernel sets the Task ID of this task to this variable at the initialization. User can refer this value but should not change.

String name

Task name string. This should be a null-terminated string and the maximum length is 16 (including the null character).

Uns ttyp

Task type flags. See 2.3.3.11 for the bit definitions. Uns (*rcv_snd)()

This function defines the task action when it received WDSND (Word Receiving task), BKSND (Global Block Receiving task) or BKSNDP (Private Block Receiving task) command. The number of the arguments varies with the received command. ♦ For WDSND

Uns (*rcv_snd)(struct dsptask *task, Uns data)

The task is the pointer for dsptask structure of this task. The data is the received word data.

♦ For BKSND Uns (*rcv_snd)(struct dsptask *task, Uns bid, Uns cnt)

The task is the pointer for dsptask structure of this task. The bid is the received BID. The cnt is the valid data count. It can be assumed that the received bid and cnt are valid and the programmer doesn’t need to check for the validity in this function.

♦ For BKSNDP Uns (*rcv_snd)(struct dsptask *task, Uns cnt)

The task is the pointer for dsptask structure of this task. The cnt is the valid data count.

This function should return zero on normal completion, but if an error occurred, it should return EID which will be reported to ARM with ERR command. When DSP received BKSND command for the Block Receiving task from ARM, the targeted task becomes the owner of the IPBUF line used in this block transfer. This task is responsible for the lock control of the IPBUF. It can release or reuse for

Page 77: Linux DSP Gateway Specification - SourceForge

77 (126)

next BKSND to ARM. If it is not needed anymore, it should be released with unuse_ipbuf() API function.

Uns (*rcv_req)()

This function defines the task action when it received WDREQ or BKREQ command. The number of the arguments varies with the received command. ♦ For WDREQ

Uns (*rcv_req)(struct dsptask *task)

The task is the pointer for dsptask structure of this task.

♦ For BKREQ Uns (*rcv_req)(struct dsptask *task, Uns cnt)

The task is the pointer for dsptask structure of this task. The cnt is the valid data count. It can be assumed that the received cnt is valid and the programmer doesn’t need to check for the validity in this function.

This function should return zero on normal completion, but if an error occurred, it should return EID which will be reported to ARM with ERR command. This function pointer can be NULL for Active Sending task since it never receives WDREQ or BKREQ command.

Uns (*rcv_tctl)()

This function defines the task action when it received TCTL command. See 2.3.3.8 for TCTL command. The strict prototype of this function should be Uns (*rcv_tctl)(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg);

But for backward compatibility, Uns (*rcv_tctl)(struct dsptask *task, Uns ctlcmd);

is still valid. The task is the pointer for dsptask structure of this task. The ctlcmd is the value of the mailbox data register with the received TCTL command. Table 5-1 shows the ctlcmd definition. The user can define TCTL commands in the range of ‘User-defined’.

Table 5-1: ctlcmd definition

Code Range Description 0x0000 – 0x007f System Command

0x0000 TINIT Task Initialize 0x0001 TEN Task Enable 0x0002 TDIS Task Disable 0x0003 TCLR Task Clear 0x0004 TKILL Task Kill

0x0005 | 0x007f

Reserved

0x0080 – 0x00ff User-defined (No parameter, No return value) This range is kept for backward compatibility. DO NOT define new commands in this range.

0x0100 - 0x7fff Reserved

Page 78: Linux DSP Gateway Specification - SourceForge

78 (126)

0x8000 - 0x80ff User-defined (No parameter, No return value) 0x8100 - 0x81ff User-defined (1 parameter, No return value) 0x8200 - 0x8fff Reserved 0x9000 - 0x90ff User-defined (No parameter, have return value) 0x9100 - 0x91ff User-defined (1 parameter, have return value) 0x9200 - 0xffff Reserved

The ret is the value to be sent back to ARM as the return value for the ioctl. It is used only in the ctlcmds which have return value (i.e. 0x9000 – 0x90ff and 0x9100 – 0x91ff). The arg is the parameter sent from ARM as the argument for the ioctl. It can be used only in the ctlcmds which have parameter (i.e. 0x8100 – 0x81ff and 0x9100 – 0x91ff). This function should return zero on normal completion, but if an error occurred, it should return EID which will be reported to ARM with ERR command. it should return MBCMD_EID_BADTCTL for ctlcmds not defined for this task. List 5-2 shows an example of the rcv_tctl() implementation. If the tokliBIOS receives that value from this function, it performs default action for the ctlcmd. TINIT ctlcmd is called at the task initialization. TCLR ctlcmd is called before the task is deleted by TDEL:SAFE mailbox command. (This occurs only if it is an on-demand task) TKILL ctlcmd is called before the task is killed by TDEL:KILL mailbox command. (This occurs only if it is an on-demand task) Another difference from TCLR ctlcmd is that TKILL ctlcmd is executed by the supertask, while TCLR ctlcmd is executed with an user task’s context. This is so that the user task can be cleared by the supertask, even if the user task got stuck and can’t execute clean-up code by itself. Therefore the user should implement the TKILL ctlcmd carefully not to get stuck within it, because a failure in it will cause the whole system’s hang-up.

List 5-2: rcv_tctl( ) implementation example Uns t1_rcv_tctl(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg) { switch(ctlcmd) { case USER_DEFINED_TCTL_COMMAND: /* * user program here. */ return 0; default: return MBCMD_EID_BADTCTL; } }

This function pointer can be NULL if there is nothing to do specifically for this task.

struct TSK_Attrs *tsk_attrs

This structure is defined in <tsk.h> for DSP/BIOS. The programmer can specify the DSP/BIOS TSK property, priority, stack size and others for this task by setting up the members of this structure. This structure is passed to the TSK_create() call in the tokliBIOS kernel. This structure pointer can be NULL if the default value is OK for this task. typedef struct TSK_Attrs { Int property; /* task priority */ Ptr stack; /* stack supplied */ Uns stacksize; /* size of stack */ Uns sysstacksize; /* size of system stack */ Int stackseg; /* segment to allocate stack from */ Ptr environ; /* environment pointer */ String name; /* printable name */ Bool exitflag; /* FALSE for server tasks */

Page 79: Linux DSP Gateway Specification - SourceForge

79 (126)

} TSK_Attrs;

Default values of the members of this structure defined in the tokliBIOS library are followings.

property = DSPTASK_DEFAULT_PRIORITY (=2) stack = NULL; stacksize = DSPTASK_DEFAULT_STACKSIZE (=512) sysstacksize = DSPTASK_DEFAULT_SYSSTACKESIZE (=256) stackseg = MEM->MALLOCSEG environ = NULL name = (name in the dsptask structure) exitflag = TRUE

struct mmap_info *mmap_info

This is pointer for the mmap information. By setting this structure, mmap() for this task in Linux application is enabled. Note that the buffer block for mmap must be placed in SDRAM. mmap() doesn’t support the shared memory in DARAM or SARAM.

struct mmap_info { Void *start; LgUns length; };

start Start address of the buffer block to share with ARM. This needs to be aligned with 2k words boundary.

length Buffer block length. This needs to be multiple of 2k words. Void *udata

This pointer is for user data. The user can use this for the data used throughout the task. The tokliBIOS kernel never touches this pointer nor pointed data.

5.6. Task API

The DSP task programmer can use following task API functions / data in the task functions. In addition to these APIs, DSP/BIOS API functions (TSK_create() for example) can be used. The task functions, rcv_snd(), rcv_req() and rcv_tctl() are called in the DSP/BIOS TSK context and there are no limitations to use DSP/BIOS APIs in them. extern Uns *ipbuf_d[]; extern Uns get_free_ipbuf(struct dsptask *task); extern Void unuse_ipbuf(struct dsptask *task, Uns bid); extern Void register_tq_1s(struct dsptask *task, Uns (*f)(struct dsptask *task)); extern Void unregister_tq_1s(struct dsptask *task, Int id); extern Void wdsnd(struct dsptask *task, Uns data); extern Void bksnd(struct dsptask *task, Uns bid, Uns cnt); extern Void bksndp(struct dsptask *task, Void *data, Uns cnt); extern Void wdreq(struct dsptask *task); extern Void bkreq(struct dsptask *task, Uns cnt); extern Void bkreqp(struct dsptask *task, Void *data, Uns cnt); extern Void cmderr(struct dsptask *task, Uns eid); extern Void dbg(struct dsptask *task, Char *fmt, ...); extern Void enable_domain(Uns val); extern Void disable_domain(Uns val); extern Void poll_disable(struct dsptask *task);

Page 80: Linux DSP Gateway Specification - SourceForge

80 (126)

extern Void poll_exclude(struct dsptask *task);

Uns *ipbuf_d[]

Global IPBUF data pointer. A task can access data field of the Global IPBUF by ipbuf_d[bid]. It should access only to the Global IPBUF line which was received from ARM with BKSND command or obtained with get_free_ipbuf() API function. When the task is releasing its own IPBUF line, it should use unuse_ipbuf() API function.

Uns get_free_ipbuf(struct dsptask *task)

A task can allocate an IPBUF line for BKSND command with this API function.

Arguments task the dsptask structure pointer of this task

Return Value SUCCESS: Valid BID FAILURE: MBCMD_BID_NULL (0xffff)

Void unuse_ipbuf(struct dsptask *task, Uns bid)

A task can release its own IPBUF line with this API function. If there are enough free IPBUF lines in DSP side, this causes BKYLD command to ARM.

Arguments task the dsptask structure pointer of this task bid the BID to be released

Return Value none

Void *register_tq_1s(struct dsptask *task, Uns (*f)(struct dsptask *task))

A task can register the function to be processed to the 1-sec Timer Queue (See 5.7).

Arguments task the dsptask structure pointer of this task f the pointer to the function to be registered

Return Value SUCCESS: the id value of the queue entry FAILURE: MEM_ILLEGAL

Void unregister_tq_1s(struct dsptask *task, Void *id)

A task can unregister the function specified with the id from the 1-sec Timer Queue.

Arguments task the dsptask structure pointer of this task id the id obtained by register_tq_1s()

Return Value none

Void wdsnd(struct dsptask *task, Uns data)

A task can issue a WDSND command with this API function.

Arguments task the dsptask structure pointer of this task

Page 81: Linux DSP Gateway Specification - SourceForge

81 (126)

data the word data to be sent

Return Value none

Void bksnd(struct dsptask *task, Uns bid, Uns cnt)

A task can issue a BKSND command with this API function.

Arguments task the dsptask structure pointer of this task bid the BID used in this transaction cnt the word count to be sent

Return Value none

Void bksndp(struct dsptask *task, Void *data, Uns cnt)

A task can issue a BKSNDP command with this API function.

Arguments task the dsptask structure pointer of this task data the address of the data to be sent cnt the word count to be sent

Return Value none

Void wdreq(struct dsptask *task)

A task can issue a WDREQ command with this API function.

Arguments task the dsptask structure pointer of this task

Return Value none

Void bkreq(struct dsptask *task, Uns cnt)

A task can issue a BKREQ command with this API function.

Arguments task the dsptask structure pointer of this task cnt the word count to be requested

Return Value none

Void bkreqp(struct dsptask *task, Void *data, Uns cnt)

A task can issue a BKREQP command with this API function.

Arguments task the dsptask structure pointer of this task data is the address of the data buffer prepared for following BKSNDP

transaction cnt the word count to be requested

Return Value

Page 82: Linux DSP Gateway Specification - SourceForge

82 (126)

none Void cmderr(struct dsptask *task, Uns eid)

A task can issue a ERR command with this API function. Note that if any error occurred in the task functions, rcv_snd(), rcv_req() and rcv_tctl(), the application doesn’t need to send ERR command using this API function but just return EID. The tokliBIOS kernel takes care of sending ERR command when those function returns non-zero value. This API is used in the user’s TSK context.

Arguments task the dsptask structure pointer of this task eid the error ID of the error cause

Return Value none

Void dbg(struct dsptask *task, Char *fmt, ...)

A task can issue a DBG command with this API function. The debug message is transferred to ARM through dbgbuf. One debug message should not be larger than 256 words. Since this buffer is not protected with read completion by ARM, but DSP writes to there arbitrary, the debug messages can be corrupted if the buffer overflow occurred.

Arguments task the dsptask structure pointer of this task fmt the print format, as used in printf-like functions

Return Value none

Void enable_domain(Uns val) Void disable_domain(Uns val)

A task can control the ICR register value through these APIs. For example, when a DSP task uses a DMA engine, it may need to issue enable_domain(_ICR_DMA_IDLE_DOMAIN) before use and disable_domain(_ICR_DMA_IDLE_DOMAIN) after use.

Arguments val the bit mask of ICR register

Return Value none

Void poll_disable(struct dsptask *task)

A task can temporary disable to be polled with this API function. Since POLL mailbox command will time out in 10 seconds, if this task can spend more than 10 seconds for one callback functions (rcv_snd, rcv_req or rcv_tctl), it should issue poll_disable() in the beginning of that callback. This effect is temporary, and polling will be re-enabled automatically after completion of this callback. See 5.9 for more detail of polling mechanism.

Arguments task the dsptask structure pointer of this task

Return Value none

Page 83: Linux DSP Gateway Specification - SourceForge

83 (126)

Void poll_exclude(struct dsptask *task)

A task can permanently disable to be polled with this API function. Once the task issue the poll_exclude(), it will never be polled. See 5.9 for more detail in polling mechanism.

Arguments task the dsptask structure pointer of this task

Return Value none

5.7. Global IPBUF Allocation / Freeing Rule

The Global IPBUF owner transition is shown in Figure 5-2. Figure 5-2: Global IPBUF Owner Transition

DSP ARM(Linux)

Owned by task

Free IPBUF Pool

Owned by task

Free IPBUF Pool

BKSND

BKYLD

get_free_ipbuf() unuse_ipbuf()

BKSND

BKYLD

user space

kernel space

user task

tokliBIOS

get_free_ipbuf() unuse_ipbuf()

copied by read() system call

copied by write() system call

DSP task applications take part in the IPBUF owner transition. If any of DSP applications handles it wrong, it will break this ecosystem. So the DSP application programmer should take care of it. When the Linux application calls write() system call, ARM sends BKSND command to DSP, then the rcv_snd() function in the DSP user task is called. From this point, this task owns the IPBUF line sent with BKSND command until it releases the line with unuse_ipbuf() API or sends back it to ARM with bksnd() API. 5.8. Timer Queue

The Timer Queue is link-listed. All registered functions are executed at every 1 second. The function is registered to the Timer Quene with register_tq_1s() API and deleted with unregister_tq_1s() API. 5.9. Polling Mechanism

The polling mechanism is shown in Figure 5-3.

Page 84: Linux DSP Gateway Specification - SourceForge

84 (126)

Figure 5-3: Polling mechanism

DSP

ARM

POLL request POLL response

Task 3

POLL

Task 2

POLL

Task 1

POLL

Mailbox Queue Mailbox Queue Mailbox Queue

POLL response flags

When a POLL request is received in DSP, it is distributed to all tasks and registered in the MBQs (Mailbox Queue). When a task found a POLL command in the MBQ, it puts a response to the POLL response flag. This is automatically done in the DSP kernel, and the user doesn’t need to take care about it. However, it should be noted that all tasks must respond to POLL within 10 seconds. If some task can’t meet this requirement, it needs to issue poll_disable() or poll_exclude() API function, so that it is excluded from POLL request distribution. 5.10. Endianism

The endianism is little bit tricky issue in the OMAP platform, since ARM and DSP works upon different endianism strategies. The DSP Gateway is designed so that the application programmer can handle word (16-bit) structured data in same manner in both processors. For example:

There is short buf16[4] in Linux, and let’s assume values shown in List 5-3.

List 5-3: Value of 16-bit data array from ARM view buf16[0] = 0x0123 buf16[1] = 0x4567 buf16[2] = 0x89ab buf16[3] = 0xcdef

And do write(fd, buf16, 4*sizeof(short))

then it is seen in DSP, ipbuf_d[bid] as a copy of buf16.

List 5-4: Value of 16-bit data array from DSP view ipbuf_d[bid][0] = 0x0123 ipbuf_d[bid][1] = 0x4567 ipbuf_d[bid][2] = 0x89ab ipbuf_d[bid][3] = 0xcdef

This is the principle concept of the data transfer in the DSP Gateway.

Page 85: Linux DSP Gateway Specification - SourceForge

85 (126)

But 32-bit data cannot handled in this way. The upper 16-bit and the lower 16-bit are swapped between ARM and DSP. For example:

There is long buf32[2] in Linux, and let’s assume values shown in List 5-5. List 5-5: Value of 32-bit data array from ARM view buf32[0] = 0x01234567 buf32[1] = 0x89abcdef

And do write(fd, buf32, 2*sizeof(long))

Then it is seen in DSP word-swapped values, if you just cast the ipbuf_d as 32-bit data like shown in List 5-6.

List 5-6: Value of 32-bit data array from DSP view *(LgUns*)&ipbuf_d[bid][0] = 0x45670123 *(LgUns*)&ipbuf_d[bid][2] = 0xcdef89ab

To fix this situation, the received data need to be performed word-swap operation as shown in List 5-7.

List 5-7: word-swap operation LgUns d32[2]; d32[0] = ((LgUns)ipbuf_d[bid][1] << 16) | ipbuf_d[bid][0]; d32[1] = ((LgUns)ipbuf_d[bid][3] << 16) | ipbuf_d[bid][2];

Then you can see as List 5-8. List 5-8: corrected 32-bit data d32[0] = 0x01234567 d32[1] = 0x89abcdef

Or if the IPBUF is placed at DARAM or SARAM space, it can be accessed in word-swapped style by accessing as long word type at odd address as shown in List 5-9, but this is not recommended since it cannot be applied for external memory, and may spoil the portability of your code.

List 5-9: 32-bit data with odd-address access *(LgUns*)&ipbuf_d[bid][1] = 0x01234567 *(LgUns*)&ipbuf_d[bid][3] = 0x89abcdef

5.11. System Parameters

User should declare Global IPBUF with “DECLARE_IPBUF()” at somewhere in the system, irrespective of whether it is used or not. In case the Global IPBUF is not needed at all, “DECLARE_IPBUF(1, 1)” can be used for the minimum allocation. 5.12. Example

This section describes an example of the DSP application and how to compile it as a static task. If you are willing to generate a dynamic task, skip this section and refer to [3]. 5.12.1. sysinfo.c

The Global IPBUF is declared here. By “DECLARE_IPBUF()”, the Glogal IPBUF is created in “ipbuf” section.

Page 86: Linux DSP Gateway Specification - SourceForge

86 (126)

List 5-10: sysinfo.c example

#include "tokliBIOS.h" DECLARE_IPBUF(0x80, 10);

5.12.2. task_test2.c

A DSP task example. The bkdata[] is set as the udata in the struct dsptask and it is accessed throughout this task.

List 5-11: DSP task example /* * task_test2.c * DSP task example */ #include <std.h> #include "tokliBIOS.h" static Uns t2_rcv_bksnd(struct dsptask *task, Uns bid, Uns cnt) { memcpy(task->udata, ipbuf_d[bid], cnt); unuse_ipbuf(task, bid); return 0; } static Uns t2_rcv_bkreq(struct dsptask *task, Uns cnt) { Uns bid; bid = get_free_ipbuf(task); if (bid == MBCMD_BID_NULL) return MBCMD_EID_STVBUF; memcpy(ipbuf_d[bid], task->udata, cnt); bksnd(task, bid, cnt); return 0; } static Uns bkdata[128]; #pragma DATA_SECTION(task_test2, "dspgw_task") struct dsptask task_test2 = { TID_MAGIC, /* tid */ "test2", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_GBMD | MBCMD_TTYP_BKDM | MBCMD_TTYP_BKMD | MBCMD_TTYP_PSND | MBCMD_TTYP_PRCV, /* ttyp: passive block snd, passive block rcv */ t2_rcv_bksnd, /* rcv_snd */ t2_rcv_bkreq, /* rcv_req */ NULL, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ bkdata /* udata */ };

Page 87: Linux DSP Gateway Specification - SourceForge

87 (126)

5.12.3. ex_task.cmd

The “ipbuf” section is placed in DARAM. All other sections are placed according to the tokliBIOScfg.cmd and tokliBIOS.cmd. Note: Each IPBUF line should not cross the 64k-word boundary.

List 5-12: linker command file example -l tokliBIOScfg.cmd -l tokliBIOS.cmd MEMORY { EXRAM: origin = 0x100000, len = 0x100000 } SECTIONS { ipbuf: align = 0x8000 {} > EXRAM shared_buf: align = 0x1000 {} > EXRAM dbgbuf: align = 0x4 {} > EXRAM }

5.12.4. Makefile

List 5-13 shows an example of Makefile for linux dsp tools.

List 5-13: Makefile example # # Makefile for ex_task.out, for Linux DSP Tools # all: .all endif none: @echo "please specify any target. valid targets are:" @echo " omap1" @echo " omap2" omap1: make all ARCH=omap1 omap2: make all ARCH=omap2 include ../Makefile.inc TOKLI_DIR = ../../../tokliBIOS DEBUG = n ifeq "$(DEBUG)" "y" CFLAGS += -g -D_DEBUG endif LIBS = -l../../../lib/tokliBIOS.lib INCD += -I../../../include LIBD += -I../../../lib TRGT = ex_task.out OBJS = ¥ sysinfo.obj ¥

Page 88: Linux DSP Gateway Specification - SourceForge

88 (126)

task_test1.obj ¥ : endiantest.obj CMDS = ex_task.cmd .all: $(TRGT) clean: -rm $(TRGT) $(OBJS) ex_task.out: $(OBJS) $(CMDS) ../../../lib/tokliBIOS.lib $(LD) $(LDFLAGS) $(LIBD) $(LIBS) $(OBJS) $(CMDS) -o$@ ex_task.out: $(OBJS) $(CMDS) $(TOKLI_DIR)/tokliBIOS.lib $(LD) $(LDFLAGS) $(LIBD) $(LIBS) $(OBJS) $(CMDS) -o$@

5.12.5. Make

Make command requires an argument to specify a target, OMAP1 or OMAP2. If you would like to build for OMAP2, type command as below.

% make omap2 make all ARCH=omap2 make[1]: Entering directory `/tmp/dsp_gateway/public/release_3.3.1/source/dspgw-3.3.1-dsp/src/apps/ex_task' /usr/local/ti_dsptools-2420/cgtools/bin/cl55 -q -ml -d_2420_ -vcore:3.0 -DCONFIG_ARCH_OMAP2 -i/usr/local/ti_dsptools-2420/cgtools/include -i/usr/local/ti_dsptools-2420/bios_5_10/packages/ti/bios/include -I../../../include sysinfo.c : /usr/local/ti_dsptools-2420/cgtools/bin/cl55 -z -q -c -x -i/usr/local/ti_dsptools-2420/cgtools/lib -i/usr/local/ti_dsptools-2420/bios_5_10/packages/ti/bios/lib -I../../../lib -l../../../lib/tokliBIOS.lib sysinfo.obj task_test1.obj task_test2.obj task_test3.obj task_test4.obj task_test5.obj task_test6.obj task_test7.obj task_test8.obj hellotimer.obj endiantest.obj ex_task.cmd -oex_task.out <Linking> make[1]: Leaving directory `/tmp/dsp_gateway/public/release_3.3.1/source/dspgw-3.3.1-dsp/src/apps/ex_task'

Some of compiler and linker options which are set in CFLAGS and LDFLAGS are explained as below. (More information are described in Makefile.inc)

CFLAGS: -ml Large memory model. LDFLAGS: -c ROM initialization. LDFLAGS: -cr RAM initialization

After issuing make command, you will have following files in current directory. “ex_task.out” is the DSP program binary.

% ls endiantest.c ex_task.out Makefile task_test1.c task_test2.obj task_test4.c task_test5.obj task_test7.c task_test8.obj endiantest.obj hellotimer.c sysinfo.c task_test1.obj task_test3.c task_test4.obj task_test6.c task_test7.obj ex_task.cmd hellotimer.obj sysinfo.obj task_test2.c task_test3.obj task_test5.c task_test6.obj task_test8.c

Page 89: Linux DSP Gateway Specification - SourceForge

89 (126)

6. DSP GATEWAY SYSTEM KERNEL OVERVIEW

6.1. Overview

Figure 6-1: DSP Gateway system kernel Block Chart

DSP “task1”

“task2” “task3”

Mailbox interrupt handler

DSP system kernel (tokliBIOS)

DSP/BIOS TSK (user task)

task API

MBQ

DSP/BIOS TSK (supertask)

Mailbox

Mailbox

Timer1 QueueMBQ

BKSND BKREQ BKSND

REGRW f1 f2

TIMER1

rcv_snd( ) function

rcv_req( ) function

rcv_tctl( ) function

timer callback function: f1

DSP/BIOS TSK (user task)

DSP/BIOS TSK (user task)

DSP/BIOS TSK (idle task)

DSP/BIOS PRD (PRD1: 1s timer)

Figure 6-1 shows the block chart of the DSP Gateway system kernel in DSP side. The programmer can build a DSP application by preparing task functions (see 5.5) and linking with the DSP Gateway system kernel library, ‘tokliBIOS.lib’. How to generate it is instructed by [1]. 6.2. DSP/BIOS Entities

The system kernel is developed upon TI’s DSP/BIOS. In this section, HWI, TSK and PRD entities used in the system kernel are summarized. 6.2.1. HWI

Mailbox and Watchdog Timer interrupts are used.

Page 90: Linux DSP Gateway Specification - SourceForge

90 (126)

6.2.1.1. Mailbox Interrupt

The Mailbox Interrupt is the mechanism for the inter-processor communication between ARM and DSP. The mailbox interrupt handler is invoked when this interrupt occurs. It reads the mailbox registers, interprets the mailbox command then adds the command to the mailbox queue in appropriate user task or the supertask. 6.2.1.2. Watchdog Timer Interrupt

The fault tolerance function in the tokliBIOS kernel is implemented using the watchdog timer. The watchdog timer can be configured in two ways, the watchdog mode and the timer mode. In this library, the watchdog timer is used in the timer mode. In this mode the interrupt handler is invoked when the watchdog timer expires. The interrupt handler reports this situation to ARM with ERR:WDT mailbox command, then it is observed through /dev/dspctl/err device. The expiration of the watchdog timer means that the idle task has not executed at all for about 20 seconds, because of a bug in the user task. 6.2.2. TSK

User tasks are executed in TSK contexts, along with two TSKs for system (supertask and idle task) and two PRD functions. 6.2.2.1. User Tasks

The user task is executed in TSK context. The priority of the TSK can be set in the range of 2 to 14. Each user task has a mailbox queue (MBQ), to which the received mailbox commands are registered. The TSK executes the commands in the queue sequentially, calling corresponding task functions in the dsptask structure of the user task. In this way, order between two mailbox commands directed one task is retained. The latter command never processed before the former command is completed. 6.2.2.2. Supertask

The supertask is the TSK for system. The priority of the supertask is 15, higher than any user tasks. The spuertask has a mailbox queue (MBQ) as well, to which the received mailbox commands are registered. The supertask executes commands for system (i.e. BKYLD, DSPCFG, REGRW, GETVAR, SETVAR, TADD and TDEL). 6.2.2.3. Sleep Task

The Sleep task is the TSK which is executed when all other TSKs have nothing to do. The priority of the idle task is 1, lower than any user tasks. The idle task issues IDLE instruction to reduce power consumption, after setting the ICR register. The loading value for ICR register can be controlled from Linux through /dev/dspctl device or /sys/devices/platform/dsp/icrmask entry. 6.2.3. PRD

Following two PRD entities are used.

Page 91: Linux DSP Gateway Specification - SourceForge

91 (126)

6.2.3.1. PRD0

PRD0 is invoked at every 10ms. This calls TSK_yield() to initiate task switch between TSKs. 6.2.3.2. PRD1

PRD1 is invoked at every 1s. In this context, all functions registered in the 1-sec Timer Queue are executed.

Page 92: Linux DSP Gateway Specification - SourceForge

92 (126)

7. DSP PROGRAM EXECUTION ON THE TARGET MACHINE

An example execution of a DSP-enabled program and utility are shown in this chapter. 7.1. Files to be prepared on ARM(Linux) side

Following files should be prepared on ARM(Linux) side for this example.

Table 7-1: Files to be prepared on the target machine

File Description /sbin/dspctl DSP control utility / program loader (See Appendix A) /root/demo_console.out DSP program binary /root/demo_console ARM side test program for demo_console.out

7.2. DSP-enabled program execution

7.2.1. DSP program loading and starting

List 7-1: DSP program loading and starting # dspctl start ./demo_console.out loading ./demo_console.out... dspgw_task : adr = 0x00d784, size= 36 dspgw_version : adr = 0x000000, size= 8 ... ignored. SARAM_seq : adr = 0x010000, size= 8 ... initialized. DARAM_seq : adr = 0x000100, size= 8 ... initialized. SDRAM_seq : adr = 0xfffd00, size= 8 ... initialized. SDRAM_system_data : adr = 0xfffd08, size= 136 ... initialized. : .sysinit : adr = 0x017efc, size= 864 ... initialized. .hwi : adr = 0x010000, size= 0 .SARAM$heap : adr = 0x01825c, size= 16 .hwi_vec : adr = 0xffff00, size= 256 ... initialized. ipbuf : adr = 0x00d7a8, size= 14 ... initialized. dbgbuf : adr = 0x00d7b6, size= 4096 ... initialized. setting DSP reset vector to 0x0181ee releasing DSP reset DSP configuration ... succeeded (kernel message) omapdsp: found 1 task(s) omapdsp: task 0: name demo_console omapdsp: taskdev demo_console enabled. (See dsptask devices) #ls -l /dev/dsptask* crw-rw-rw- 1 root root 97, 0 Jan 1 01:43 dsptask0 dsptask: lrwxrwxrwx 1 root root 13 Jan 1 01:43 demo_console -> /dev/dsptask0

Page 93: Linux DSP Gateway Specification - SourceForge

93 (126)

7.2.2. Test Run

List 7-2: DSP program test running

(Run ARM side test program to check loaded DSP task is working) # ./demo_console Congratulations! DSP is working!

7.2.3. Stop and unload DSP program

# dspctl stop releasing resources for DSP DSP reset

In Appendix B: DSP Task Examples and Mailbox COMMAND EXCHANGE Commentary, DSP binary “ex_task.out” is introduced and several DSP task examples included in it are explained.

Page 94: Linux DSP Gateway Specification - SourceForge

94 (126)

REFERENCES • [1] Generating tokliBIOS.lib for DSP Gateway 3.3.1

• [2] Updating Application for DSP Gateway 3.3.1, Nokia

• [3] DSP Gateway Dynamic Loader Daemon (dsp_dld) Specification rev 1.6, Nokia

• [4] https://www-a.ti.com/downloads/sds_support/targetcontent/LinuxDspTools/index.html

• [5] Texas Instruments, “OMAP2420 Technical Reference Manual”, Version E

Page 95: Linux DSP Gateway Specification - SourceForge

95 (126)

APPENDIX A: dspctl UTILITY dspctl is the DSP control utility program for the DSP Gateway. The user can load DSP program, control DSP reset, perform DSP configuration and map external memory for DSP with this utility. In addition, it is possible to send mailbox commands to DSP for the debug purpose. Usage:

dspctl <command> [options...] commands are:

start <cofffile> stop version <cofffile> load <cofffile> run (= unreset) reset setrstvect <addr> gbl_idle cpu_idle suspend resume dspcfg dspuncfg poll kmem_reserve <request size> kmem_release exmap <dspadr> <request size> exunmap <dspadr> mapflush fbexport <dspadr> mmuinit mmuitack mkdev <devname> rmdev <devname> tadd <minor> <addr> tdel <minor> getvar <varid> setvar <varid> <data> regread [-io] <adr> regwrite [-io] <adr> <val> runlevel <user|super> mbsend <cmd> <data>

1) start

Before using DSP task applications, the user needs to load the DSP application program to the DSP memory, release the DSP reset, and configure the DSP system by obtaining information from DSP application. These steps are done by ‘load’, ‘unreset’ and ‘dspcfg’ commands of dspctl respectively, and the ‘start’ command performs all of them. In the dspcfg phase, DSP task devices are created and after that the DSP tasks are ready to use from Linux processes.

Page 96: Linux DSP Gateway Specification - SourceForge

96 (126)

List A- 0-1: dspctl start # dspctl start ex_task.out loading ex_task.out... .vers : adr = 0x000000, size= 120 ... ignored. .sysstack : adr = 0x000100, size= 512 ... initialized. .clk : adr = 0x000300, size= 8 ... initialized. .prd : adr = 0x000308, size= 48 ... initialized. .swi : adr = 0x000338, size= 120 ... initialized. : SDRAM_seq : adr = 0xfffd00, size= 8 ... initialized. SDRAM_system_data : adr = 0xfffd08, size= 136 ... initialized. sleep_code : adr = 0x00c8d0, size= 280 ... initialized. ipbuf : adr = 0x100000, size= 1136 ... initialized. shared_buf : adr = 0x100000, size= 0 dbgbuf : adr = 0x100470, size= 4096 ... initialized. warning: found zero-sized cinit entry at 0xc72 .cinit : adr = 0x010000, size= 3188 ... .bss variables are initialized. setting DSP reset vector to 0x018a87 releasing DSP reset DSP configuration ... succeeded (kernel message) found 12 task(s) task 0: name test8a taskdev test8a enabled. task 1: name test8b taskdev test8b enabled. task 2: name test8c : task 11: name test4 taskdev test4 enabled. (See dsp devices) # ls -l /dev/dsptask lrwxrwxrwx 1 root root 13 Apr 14 18:47 endiantest -> /dev/dsptask6 lrwxrwxrwx 1 root root 13 Apr 14 18:47 hellotimer -> /dev/dsptask5 lrwxrwxrwx 1 root root 13 Apr 14 18:47 test1 -> /dev/dsptask8 :

2) stop

After using DSP tasks, the user needs to clear the allocated resources and remove the created device files for the DSP system, then stop (reset) the DSP. These steps are done by ‘dspuncfg’ and ‘reset’ commands of dspctl respectively, and the ‘stop’ command performs all of them.

List A- 0-2: dspctl stop # dspctl stop releasing resources for DSP DSP reset (kernel message) omapdsp: /dev/dsptask/test2 was deleted.

Page 97: Linux DSP Gateway Specification - SourceForge

97 (126)

3) version

This command shows the DSP binary’s version stamp.

List A- 0-3: dspctl version # dspctl version ex_task.out DSP Gateway binary version 3.3.0.0

4) load

This command loads the DSP application binary (*.out file) to the DSP memory. This step is included in ‘start’ command, and usually the user doesn’t need to use this command, except in case that user want to do ‘load’, ‘unreset’ and ‘dspcfg’ step-by-step. 5) run (= unreset) / reset

The run command releases the reset of DSP. The reset command resets DSP. These procedures are included in ‘start’ and ‘stop’ command respectively, and in normal case the user doesn’t need to use these commands. 6) setrstvect (for debug use)

This command sets the reset vector to jump to specified address at releasing the reset. Usually this step is automatically done in ‘load’ command. When the user wants to do it manually, use this command. 7) gbl_idle / cpu_idle (only for OMAP1)

This command brings DSP into idle mode. gbl_idle forces DSP to enter global idle regardless of icr_mask value, while cpu_idle follows icr_mask value to set ICR. This command is only supported for OMAP1 architecture. See ‘GBL_IDLE’ and ‘CPU_IDLE’ in 3.3.1 for more details. 8) suspend, resume

The suspend command brings DSP to reset, after DSP runs suspend code. The resume command resumes DSP to the previous state, as before suspending. 9) dspcfg, dspuncfg

These commands configure / unconfigure the DSP system. These steps are included in ‘start’ or ‘stop’ command, and usually the user doesn’t need to use these commands. 10) poll

This command issues POLL mailbox command to DSP and waits the response from dsp.

Page 98: Linux DSP Gateway Specification - SourceForge

98 (126)

11) kmem_reserve, kmem_release

‘kmem_reserve’ reserves kernel memory blocks in the DSP driver’s internal pool. The memory blocks in the pool will be served for the future ‘exmap’ command. ‘kmem_release’ releases all blocks in the pool.

List A- 0-4: dspctl exmap / exunmap

(Reserve 3MB) # dspctl kmem_reserve 300000 reserving kernel memory for DSP: size = 0x300000 3145728 (0x300000) bytes reserved. (Release the memory blocks reserved above) # dspctl kmem_release releasing kernel memory for DSP

12) exmap, exunmap

‘exmap’ allocates a buffer and maps it to DSP memory space. The user can extend the DSP memory with this command. ‘exunmap’ releases the buffer which has been allocated with ‘exmap’ command.

List A- 0-5: dspctl exmap / exunmap

(See default status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 02: P V 4KB 0xfe2000 0x48094000 L 32 03: P V 4KB 0xfdc000 0x4807c000 L 32 04: P V 4KB 0xfdd000 0x4807e000 L 32 05: P V 4KB 0xfde000 0x48080000 L 32 06: P V 4KB 0xfdf000 0x48082000 L 32 07: V 1MB 0x100000 0x83800000 L 16 lock base = 8 victim = 8 08: 1MB 0x000000 0x00000000 L 8 09: 1MB 0x000000 0x00000000 L 8 : 29: 1MB 0x000000 0x00000000 L 8 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8 (Map 64kB at 0x03_0000 in DSP memory space) # dspctl exmap 300000 10000 mapping external memory for DSP: dspadr = 0x300000, size = 0x10000 65536 (0x10000) bytes mapped.

Page 99: Linux DSP Gateway Specification - SourceForge

99 (126)

(See status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 02: P V 4KB 0xfe2000 0x48094000 L 32 03: P V 4KB 0xfdc000 0x4807c000 L 32 04: P V 4KB 0xfdd000 0x4807e000 L 32 05: P V 4KB 0xfde000 0x48080000 L 32 06: P V 4KB 0xfdf000 0x48082000 L 32 07: V 1MB 0x100000 0x83800000 L 16 08: V 64KB 0x300000 0x83fa0000 L 16 lock base = 9 victim = 9 09: 1MB 0x000000 0x00000000 L 8 10: 1MB 0x000000 0x00000000 L 8 : 29: 1MB 0x000000 0x00000000 L 8 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8 (Unmap the memory mapped above) # dspctl exunmap 300000 releasing external memory map for DSP: dspadr = 0x300000 65536 (0x10000) bytes unmapped. (See status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 02: P V 4KB 0xfe2000 0x48094000 L 32 03: P V 4KB 0xfdc000 0x4807c000 L 32 04: P V 4KB 0xfdd000 0x4807e000 L 32 05: P V 4KB 0xfde000 0x48080000 L 32 06: P V 4KB 0xfdf000 0x48082000 L 32 07: V 1MB 0x100000 0x83800000 L 16 lock base = 8 : 28: 1MB 0x000000 0x00000000 L 8 29: 1MB 0x000000 0x00000000 L 8 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8

Page 100: Linux DSP Gateway Specification - SourceForge

100 (126)

13) mapflush

This command releases all buffers which has been allocated with ‘exmap’ command or mapped to the DSP space with ‘fbexport’ command.

List A- 0-6: dspctl mapflush

(exmap to DSP) # dspctl exmap 100000 10000 mapping external memory for DSP: dspadr = 0x100000, size = 0x10000 65536 (0x10000) bytes mapped. Nokia770-15:~# dspctl exmap 200000 10000 mapping external memory for DSP: dspadr = 0x200000, size = 0x10000 65536 (0x10000) bytes mapped. (See status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 : 07: V 64KB 0x100000 0x84ef0000 L 16 08: V 64KB 0x200000 0x84f70000 L 16 lock base = 9 victim = 9 09: 1MB 0x000000 0x00000000 L 8 10: 1MB 0x000000 0x00000000 L 8 : 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8 (Flush the DSP TLB) # dspctl mapflush flush DSP TLB. (See status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 : 05: P V 4KB 0xfde000 0x48080000 L 32 06: P V 4KB 0xfdf000 0x48082000 L 32 lock base = 7 victim = 7 07: 64KB 0x100000 0x84ef0000 L 16 08: 64KB 0x200000 0x84f70000 L 16 09: 1MB 0x000000 0x00000000 L 8 : 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8

Page 101: Linux DSP Gateway Specification - SourceForge

101 (126)

14) fbexport

This command exports the frame buffer used in ARM side to the DSP memory space. After exported, DSP can write raw image data to the frame buffer directly. Note that you can specify the dspadr option for this command but it is a ‘hint’ address for mapping. The actual address can be different from the hint, because the driver tries to align the offset between the physical address and the dsp address as far as possible.

List A- 0-7: dspctl fbexport

(See default status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 : 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8 (Export framebuffer to DSP space) # dspctl fbexport 100000 mapping frame buffer to DSP space: dspadr hint = 0x100000 dspadr actual = 0x100000 770048 (0xbc000) bytes mapped. (See status of TLB) # cat /sys/devices/platform/dsp/mmu P: preserved, V: valid B: big endian, L:little endian, M: mixed page attribute ety P V size cam_va ram_pa E ES M 00: P V 4KB 0xfff000 0x87d70000 L 16 01: P V 4KB 0xfce000 0x48008000 L 32 : 06: P V 4KB 0xfdf000 0x48082000 L 32 07: V 64KB 0x100000 0x87f00000 L 16 08: V 64KB 0x110000 0x87f10000 L 16 09: V 64KB 0x120000 0x87f20000 L 16 10: V 64KB 0x130000 0x87f30000 L 16 11: V 64KB 0x140000 0x87f40000 L 16 12: V 64KB 0x150000 0x87f50000 L 16 13: V 64KB 0x160000 0x87f60000 L 16 14: V 64KB 0x170000 0x87f70000 L 16 15: V 64KB 0x180000 0x87f80000 L 16 16: V 64KB 0x190000 0x87f90000 L 16 17: V 64KB 0x1a0000 0x87fa0000 L 16 18: V 4KB 0x1b0000 0x87fb0000 L 16 19: V 4KB 0x1b1000 0x87fb1000 L 16 : 28: V 4KB 0x1ba000 0x87fba000 L 16 29: V 4KB 0x1bb000 0x87fbb000 L 16 lock base = 30 victim = 30 30: 1MB 0x000000 0x00000000 L 8 31: 1MB 0x000000 0x00000000 L 8

Page 102: Linux DSP Gateway Specification - SourceForge

102 (126)

15) mmuinit

This command initializes the DSP MMU. 16) mmuitack (for debug use)

This command sends the acknowledge toward the DSP MMU interupt after setting the DSP runlevel to RECOVERY. By doing this, you might get some info from DSP who caused the MMU fault, where, etc... but plase note that they are not guaranteed to be correct. 17) mkdev, rmdev (for debug use)

These commands creates / removes a device file for DSP on-demand task. These are usually done by the dynamic loader daemon and the user doesn’t need to do them manually. 18) tadd, tdel (for debug use)

These commands adds / deletes the DSP on-demand task to the device file. These are usually done by the dynamic loader daemon and the user doesn’t need to do them manually. 19) getvar, setvar

The user can read / write the system variables in DSP. See 2.3.3.20 for the variable definitions.

Page 103: Linux DSP Gateway Specification - SourceForge

103 (126)

20) regread, regwrite (for debug use)

The user can read / write the data in DSP memory / IO space with these commands. It can cause fatal error for the system. Use with care.

List A- 0-8: dspctl regread / regwrite

(Read TIMER1 LOAD VALUE) # dspctl regread -io 2803 DSP register read: adr=IO:0x2803, val=0xea5f (Test the timer: See the interval is 1 second) # ./hellotimer 5 time: 4800.04 Hello from DSP! time: 4801.04 Hello from DSP! time: 4802.04 Hello from DSP! time: 4803.04 Hello from DSP! time: 4804.04 Hello from DSP! (Change TIMER1 LOAD VALUE) # dspctl regwrite -io 2803 752f DSP register write: adr=IO:0x2803, val=0x752f # dspctl regread -io 2803 DSP register read: adr=IO:0x2803, val=0x752f (Test the timer again: See the interval became 0.5 second) # ./hellotimer 5 time: 4838.27 Hello from DSP! time: 4838.77 Hello from DSP! time: 4839.27 Hello from DSP! time: 4839.77 Hello from DSP! time: 4840.27 Hello from DSP!

21) runlevel

The user can set the DSP runlevel with this command. 22) mbsend (for debug use)

The user can send mailbox command manually with this command.

Page 104: Linux DSP Gateway Specification - SourceForge

104 (126)

APPENDIX B: DSP TASK EXAMPLES AND MAILBOX COMMAND EXCHANGE COMMENTARY 1) DSP configuration

List B- 0-1: Mailbox command exchange in DSP configuration phase # dspctl start ./ex_task.out loading ./ex_task.out... .vers : adr = 0x000000, size= 120 ... ignored. .sysstack : adr = 0x000100, size= 512 ... initialized. .clk : adr = 0x000300, size= 8 ... initialized. .prd : adr = 0x000308, size= 48 ... initialized. .swi : adr = 0x000338, size= 160 ... initialized. .tsk : adr = 0x0003d8, size= 264 ... initialized. : DARAM_seq : adr = 0x003ce0, size= 8 ... initialized. SDRAM_seq : adr = 0xfffd00, size= 8 ... initialized. SDRAM_system_data : adr = 0xfffd08, size= 136 ... initialized. sleep_code : adr = 0x00c8d0, size= 280 ... initialized. ipbuf : adr = 0x100000, size= 1136 ... initialized. shared_buf : adr = 0x100000, size= 0 dbgbuf : adr = 0x100470, size= 4096 ... initialized. .cinit : adr = 0x010000, size= 3188 ... .bss variables are initialized. setting DSP reset vector to 0x018a87

releasing DSP reset DSP configuration ... succeeded.

(mailbox commands) M->D, DSPCFG:CFG_REQ

(kernel message) omapdsp: found 12 task(s)

D->M, DSPCFG:CFG_PROTREV D->M, DSPCFG:CFG_SYSADRH D->M, DSPCFG:CFG_SYSADRL D->M, BKYLD D->M, BKYLD

omapdsp: task 1: name test8b omapdsp: taskdev test8b enabled.

M->D, TCFG(TID=0) D->M, TCFG(TID=0)

omapdsp: IPBUF configuration 128 words * 4 lines at 0xe0100000

#

Page 105: Linux DSP Gateway Specification - SourceForge

105 (126)

2) test1

Task Name: “test1” Task Type: passive word sending / passive word receiving This task remembers sent data from ARM up to 64 words and returns it when requested.

DSP Source Code List B- 0-2: DSP task example: test1

/* * task_test1.c */ #include <std.h> #include "tokliBIOS.h" struct t1_udata { Int wdwptr, wdrptr; Uns wddata[64]; }; static Uns t1_rcv_wdsnd(struct dsptask *task, Uns data) { struct t1_udata *udata = task->udata; udata->wddata[udata->wdwptr] = data; if (udata->wdwptr < 64) udata->wdwptr++; return 0; } static Uns t1_rcv_wdreq(struct dsptask *task) { struct t1_udata *udata = task->udata; if (udata->wdwptr == 0) return 0; wdsnd(task, udata->wddata[udata->wdrptr++]); if (udata->wdrptr == udata->wdwptr) udata->wdrptr = 0; return 0; } static Uns t1_rcv_tctl(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg) { struct t1_udata *udata = task->udata; switch (ctlcmd) { case MBCMD_TCTL_TINIT: udata->wdwptr = 0; udata->wdrptr = 0; return 0; default: return MBCMD_EID_BADTCTL; } }

Page 106: Linux DSP Gateway Specification - SourceForge

106 (126)

static struct t1_udata udata; #pragma DATA_SECTION(task_test1, "dspgw_task") struct dsptask task_test1 = { TID_MAGIC, /* tid */ "test1", /* name */ MBCMD_TTYP_WDDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_PSND | MBCMD_TTYP_PRCV, /* ttyp: passive word snd, passive word rcv */ t1_rcv_wdsnd, /* rcv_snd */ t1_rcv_wdreq, /* rcv_req */ t1_rcv_tctl, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ &udata /* udata */ };

Task Execution List B- 0-3: Mailbox command exchange in task1

(mailbox commands) # echo acyo1 > /dev/dsptask/test1 #

M->D, WDSND M->D, WDSND M->D, WDSND

# cat /dev/dsptask/test1 acyo1 acyo1 acyo1 acyo1 acyo1 : (^C) (We get the written data continuously because cat continues to read)

M->D, WDREQ D->M, WDSND M->D, WDREQ D->M, WDSND M->D, WDREQ D->M, WDSND M->D, WDREQ D->M, WDSND :

#

Page 107: Linux DSP Gateway Specification - SourceForge

107 (126)

3) test2

Task Name: “test2” Task Type: passive block sending / passive block receiving This task remembers one sent block data from ARM and returns it when requested

DSP Source Code See 5.12.2.

Task Execution List B- 0-4: Mailbox command exchange in task2

(mailbox commands) # echo “This is initial text for test2.” > initial1.txt # cat initial1.txt This is initial text for test2.

# cp initial1.txt /dev/dsptask/test2 #

M->D, BKSND(BID=2) D->M, BKYLD(BID=0)

# dd if=/dev/dsptask/test2 bs=32 count=1 This is initial text for test2.

M->D, BKREQ(CNT=16) D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

#

Page 108: Linux DSP Gateway Specification - SourceForge

108 (126)

4) test3

Task Name: “test3” Task Type: active word sending passive word receiving This task receives 1-word data, which is the iteration count and sends word data readable for ARM, for iteration count times actively.

DSP Source Code List B- 0-5: DSP task example: test3

/* * task_test3.c */ #include <std.h> #include "tokliBIOS.h" static Uns t3_rcv_wdsnd(struct dsptask *task, Uns data) { Int i; Uns wd; for (i = 0, wd = 0x0a40; i < data; i++, wd++) { wdsnd(task, wd); } return 0; } #pragma DATA_SECTION(task_test3, "dspgw_task") struct dsptask task_test3 = { TID_MAGIC, /* tid */ "test3", /* name */ MBCMD_TTYP_WDDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active word snd, passive word rcv */ t3_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ NULL /* udata */ };

Linux Frontent Program List B- 0-6: Frontend program for test3

/* * test3.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #define BUFSZ 256 void usage(char *cmd) { fprintf(stderr, "%s <repeat_count>¥n", cmd); }

Page 109: Linux DSP Gateway Specification - SourceForge

109 (126)

int main(int argc, char **argv) { int fd; unsigned short repeat; char buf[BUFSZ]; char *devfn = "/dev/dsptask/test3"; if (argc != 2) { usage(argv[0]); return 1; } repeat = atoi(argv[1]); fd = open(devfn, O_RDWR); if (fd < 0) { fprintf(stderr, "cannot open %s¥n", devfn); return 1; } write(fd, &repeat, 2); for (;;) { int cnt; cnt = read(fd, buf, BUFSZ); if (cnt < 0) { perror("read failed"); break; } write(1, buf, cnt); } close(fd); return 0; }

Task Execution List B- 0-7: Mailbox command exchange in task3

(mailbox commands) # ./test3 5 @ A B C D (^c)

M->D, WDSND D->M, WDSND D->M, WDSND D->M, WDSND D->M, WDSND D->M, WDSND

# ./test3 20 D E F G : P Q R S (^c) (We have got 20 words from DSP but we have only 32 bytes (16 words) buffer in the driver, and first 4 words have been lost)

M->D, WDSND D->M, WDSND : (20 times) D->M, WDSND

#

Page 110: Linux DSP Gateway Specification - SourceForge

110 (126)

5) test4

Task Name: “test4” Task Type: active block sending / passive word receiving This task receives 1-word data, which is the iteration count and sends block data readable for ARM, for iteration count times actively.

DSP Source Code List B- 0-8: DSP task example: test4

/* * task_test4.c */ #include <std.h> #include "tokliBIOS.h" static Void busywait(Uns cnt) { Uns i; for (i = 0; i < cnt; i++) {} } static Uns t4_rcv_wdsnd(struct dsptask *task, Uns data) { Uns bid; Int ipbuf_trycnt = 0; Int i, j, k; Uns *p; for (i = 0; i < data; i++) { ipbuf_trycnt = 0; for (;;) { bid = get_free_ipbuf(task); if (bid != MBCMD_BID_NULL) break; if (++ipbuf_trycnt >= 100) return MBCMD_EID_STVBUF; busywait(100); } p = ipbuf_d[bid]; for(j = 0; j < 4; j++) { for(k = 0; k < 30; k++) { *(p++) = 0x4141 + 0x0101 * j; } *(p++) = 0x0a00 | (0x30 + (i&0x07)); } bksnd(task, bid, 124); } return 0; } #pragma DATA_SECTION(task_test4, "dspgw_task") struct dsptask task_test4 = { TID_MAGIC, /* tid */ "test4", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_BKDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active block snd, passive word rcv */ t4_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */

Page 111: Linux DSP Gateway Specification - SourceForge

111 (126)

NULL, /* tsk_attrs */ NULL, /* mmap_info */ NULL /* udata */ };

Linux Frontent Program List B- 0-9: Frontent program for test4

/* * test4.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #define DEFAULT_BUFSZ 1024 void usage(char *cmd) { fprintf(stderr, "%s <repeat_count> [buffer size]¥n", cmd); } int main(int argc, char **argv) { int fd; unsigned short repeat; size_t bufsz = DEFAULT_BUFSZ; char *buf; char *devfn = "/dev/dsptask/test4"; if ((argc != 2) && (argc != 3)) { usage(argv[0]); return 1; } repeat = atoi(argv[1]); if (argc == 3) { bufsz = atoi(argv[2]); if (bufsz == 0) { fprintf(stderr, "invalid buffer size (%d)¥n", bufsz); } } buf = malloc(bufsz); fd = open(devfn, O_RDWR); if (fd < 0) { fprintf(stderr, "cannot open %s¥n", devfn); return 1; } printf("reading with %d bytes buffer...¥n", bufsz); write(fd, &repeat, 2); for (;;) { int cnt; cnt = read(fd, buf, bufsz); if(cnt < 0) { perror("read failed"); break; } write(1, buf, cnt); } close(fd); free(buf);

Page 112: Linux DSP Gateway Specification - SourceForge

112 (126)

return 0; }

Task Execution List B- 0-10: Mailbox command exchange in task4

(mailbox commands) # ./test4 2 AAAAAAAAAAAAAAAAAAAAAAA...AAAAAAAAAAAAAAA0 BBBBBBBBBBBBBBBBBBBBBBB...BBBBBBBBBBBBBBB0 CCCCCCCCCCCCCCCCCCCCCCC...CCCCCCCCCCCCCCC0 DDDDDDDDDDDDDDDDDDDDDDD...DDDDDDDDDDDDDDD0 AAAAAAAAAAAAAAAAAAAAAAA...AAAAAAAAAAAAAAA1 BBBBBBBBBBBBBBBBBBBBBBB...BBBBBBBBBBBBBBB1 CCCCCCCCCCCCCCCCCCCCCCC...CCCCCCCCCCCCCCC1 DDDDDDDDDDDDDDDDDDDDDDD...DDDDDDDDDDDDDDD1 (^c)

M->D, WDSND D->M, BKSND(BID=0) M->D, BKYLD(BID=2) D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

#

Page 113: Linux DSP Gateway Specification - SourceForge

113 (126)

6) test7

Task Name: “test7” Task Type: active private block sending / active private block receiving An example of Private IPBUF. This task requests 16-word data using private IPBUF. The received data is sent back to ARM also using private IPBUF with no modification.

DSP Source Code List B- 0-11: DSP task example: test7

/* * task_test7.c */ #include <std.h> #include "tokliBIOS.h" #define T7_BUF_SZ 0x10 struct t7_udata { Int *rbuf; Int *wbuf; }; static Uns t7_rcv_bksnd(struct dsptask *task, Uns cnt) { struct t7_udata *udata = task->udata; if (cnt > T7_BUF_SZ) return MBCMD_EID_BADCNT; memcpy(udata->wbuf, udata->rbuf, cnt); bksndp(task, udata->wbuf, cnt); /* echo back */ bkreqp(task, udata->rbuf, T7_BUF_SZ); return 0; } static Uns t7_rcv_tctl(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg) { struct t7_udata *udata = task->udata; switch (ctlcmd) { case MBCMD_TCTL_TINIT: memset(udata->rbuf, 0xbeef, T7_BUF_SZ); memset(udata->wbuf, 0xdead, T7_BUF_SZ); bkreqp(task, udata->rbuf, T7_BUF_SZ); return 0; default: return MBCMD_EID_BADTCTL; } } #pragma DATA_SECTION(t7_rbuf_data, "ipbuf"); #pragma DATA_SECTION(t7_wbuf_data, "ipbuf"); static Int t7_rbuf_data[T7_BUF_SZ]; static Int t7_wbuf_data[T7_BUF_SZ]; static struct t7_udata udata = { t7_rbuf_data, t7_wbuf_data }; #pragma DATA_SECTION(task_test7, "dspgw_task") struct dsptask task_test7 = { TID_MAGIC, /* tid */ "test7", /* name */

Page 114: Linux DSP Gateway Specification - SourceForge

114 (126)

MBCMD_TTYP_PVDM | MBCMD_TTYP_PVMD | MBCMD_TTYP_BKDM | MBCMD_TTYP_BKMD | MBCMD_TTYP_ASND | MBCMD_TTYP_ARCV, /* ttyp: active block snd, active block rcv */ t7_rcv_bksnd, /* rcv_snd */ NULL, /* rcv_req */ t7_rcv_tctl, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ &udata /* udata */ };

Linux Frontent Program List B- 0-12: Frontent program for test7

/* * test7.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #define BUFSZ 50 void usage(char *cmd) { fprintf(stderr, "%s <repeat_count>¥n", cmd); } int main(int argc, char **argv) { int fd; char buf[BUFSZ]; int cnt1, cnt2; char *wdata = "aaaaabbbbbcccccdddddeeeeefffffggggghhhhhiiiiijjjjj"; char *devfn = "/dev/dsptask/test7"; fd = open(devfn, O_RDWR); if (fd < 0) { fprintf(stderr, "cannot open %s¥n", devfn); return 1; } cnt1 = write(fd, wdata, BUFSZ); if (cnt1 < 0) { perror("write failed"); return 1; } fprintf(stderr, "%d bytes written¥n", cnt1); cnt2 = read(fd, buf, BUFSZ); if (cnt2 < 0) { perror("read failed"); return 1; } fprintf(stderr, "%d bytes read¥n", cnt2); write(1, buf, cnt2); putchar('¥n'); close(fd); return 0; }

Page 115: Linux DSP Gateway Specification - SourceForge

115 (126)

List B- 0-13: Mailbox command exchange in task7 (mailbox commands) D->M, BKREQP # ./test7 32 bytes written 32 bytes read aaaaabbbbbcccccdddddeeeeefffffgg

M->D, BKSNDP D->M, BKSNDP D->M, BKREQP

#

Page 116: Linux DSP Gateway Specification - SourceForge

116 (126)

7) task8

Task Name: “test8a”, “test8b”, “task8c” Task Type: active block sending / passive word receiving DSP/BIOS switching TSK example. These tasks receive 1-word data, which is the iteration count and go into busy loop in which these task sends the greeting string for iteration count times. We can observe the TSK switching by DSP/BIOS. The task8c has higher priority than other two tasks, and it occupies the DSP without yielding to other tasks until it exits from the busy loop.

DSP Source Code List B- 0-14: DSP task example: test8

/* * task_test8.c */ #include <std.h> #include <tsk.h> #include "tokliBIOS.h" #define T8A_STR "Hello from task8a! * ¥n" #define T8B_STR "Hello from task8b! * ¥n" #define T8C_STR "Hello from task8c! * ¥n" #define T8A_INT 1040000L #define T8B_INT 400000L #define T8C_INT 400000L struct t8_udata { char *s; LgUns interval; }; static Void busywait(LgUns cnt) { LgUns i; for (i = 0; i < cnt; i++) {} } static Int strcpy16to8(Char *d, Char *s) { Int cnt = 0; for (; *s; s++, d++) { *d = *s; *d |= *++s << 8; cnt++; if (!*s) return cnt; } *d = '¥0'; return cnt; } static Uns t8_rcv_wdsnd(struct dsptask *task, Uns data) { struct t8_udata *udata = task->udata; LgUns interval = udata->interval; Uns bid; Int cnt, i; if (data > 100) poll_disable(task); /* prevent POLL during this function */

Page 117: Linux DSP Gateway Specification - SourceForge

117 (126)

for (i = 0; i < data; i++) { busywait(interval); bid = get_free_ipbuf(task); if (bid == MBCMD_BID_NULL) return MBCMD_EID_STVBUF; cnt = strcpy16to8((Char *)ipbuf_d[bid], udata->s); bksnd(task, bid, cnt); } return 0; } /* * task 8a: normal priority */ static struct t8_udata udata_a = { T8A_STR, T8A_INT }; #pragma DATA_SECTION(task_test8a, "dspgw_task") struct dsptask task_test8a = { TID_MAGIC, /* tid */ "test8a", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_BKDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active block snd, passive word rcv */ t8_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ &udata_a /* udata */ }; /* * task 8b: normal priority */ static struct t8_udata udata_b = { T8B_STR, T8B_INT }; #pragma DATA_SECTION(task_test8b, "dspgw_task") struct dsptask task_test8b = { TID_MAGIC, /* tid */ "test8b", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_BKDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active block snd, passive word rcv */ t8_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ &udata_b /* udata */ }; /* * task 8c: high priority */ static struct TSK_Attrs attr_c = { DSPTASK_DEFAULT_PRIORITY+1, /* priority */ NULL, /* stack */ DSPTASK_DEFAULT_STACKSIZE, /* stacksize */ DSPTASK_DEFAULT_SYSSTACKSIZE, /* sysstacksize */ 0, /* stackseg: can't be overridden */ NULL, /* environ */ NULL, /* name: can't be overridden */

Page 118: Linux DSP Gateway Specification - SourceForge

118 (126)

TRUE /* exitflag */ }; static struct t8_udata udata_c = { T8C_STR, T8C_INT }; #pragma DATA_SECTION(task_test8c, "dspgw_task") struct dsptask task_test8c = { TID_MAGIC, /* tid */ "test8c", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_BKDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active block snd, passive word rcv */ t8_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ NULL, /* rcv_tctl */ &attr_c, /* tsk_attrs */ NULL, /* mmap_info */ &udata_c /* udata */ };

Linux Frontent Program List B- 0-15: Frontent program for test8

/* * test8.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/time.h> #define BUFSZ 256 void usage(char *cmd) { fprintf(stderr, "%s <repeat_count>¥n", cmd); } int dif_str(char *s, struct timeval *tm1, struct timeval *tm2) { int scnt; int timdiff; if (tm2->tv_sec || tm2->tv_usec) { /* non-zero */ timdiff = (tm1->tv_sec - tm2->tv_sec) * 100 + (tm1->tv_usec - tm2->tv_usec) / 10000; scnt = sprintf(s, "time : %ld.%02ld (+%2d.%02d) ", tm1->tv_sec, tm1->tv_usec / 10000, timdiff / 100, timdiff % 100); } else { scnt = sprintf(s, "time : %ld.%02ld ", tm1->tv_sec, tm1->tv_usec / 10000); } return scnt; } int main(int argc, char **argv) { int fd1, fd2, fd3; unsigned short repeat; char *devfn1 = "/dev/dsptask/test8a"; char *devfn2 = "/dev/dsptask/test8b"; char *devfn3 = "/dev/dsptask/test8c";

Page 119: Linux DSP Gateway Specification - SourceForge

119 (126)

fd_set fdset; struct timeval tm1a, tm2a, tm1b, tm2b, tm1c, tm2c; if (argc != 2) { usage(argv[0]); return 1; } repeat = atoi(argv[1]); fd1 = open(devfn1, O_RDWR); if (fd1 < 0) { fprintf(stderr, "cannot open %s¥n", devfn1); return 1; } fd2 = open(devfn2, O_RDWR); if (fd2 < 0) { fprintf(stderr, "cannot open %s¥n", devfn2); return 1; } fd3 = open(devfn3, O_RDWR); if (fd3 < 0) { fprintf(stderr, "cannot open %s¥n", devfn3); return 1; } memset(&tm2a, 0, sizeof(struct timeval)); memset(&tm2b, 0, sizeof(struct timeval)); memset(&tm2c, 0, sizeof(struct timeval)); FD_ZERO(&fdset); FD_SET(fd1, &fdset); FD_SET(fd2, &fdset); FD_SET(fd3, &fdset); write(fd1, &repeat, 2); write(fd2, &repeat, 2); write(fd3, &repeat, 2); for (;;) { fd_set testfds; int result, cnt; char buf[BUFSZ]; char s[64]; int scnt; testfds = fdset; result = select(fd3+1, &testfds, (fd_set *)0, (fd_set *)0, NULL); if (result < 0) { perror("select failed"); break; } if (FD_ISSET(fd1, &testfds)) { cnt = read(fd1, buf, BUFSZ); if (cnt < 0) { perror("read failed"); break; } gettimeofday(&tm1a, NULL); scnt = dif_str(s, &tm1a, &tm2a); write(1, s, scnt); write(1, buf, cnt); memcpy(&tm2a, &tm1a, sizeof(struct timeval)); }

Page 120: Linux DSP Gateway Specification - SourceForge

120 (126)

if (FD_ISSET(fd2, &testfds)) { cnt = read(fd2, buf, BUFSZ); if (cnt < 0) { perror("read failed"); break; } gettimeofday(&tm1b, NULL); scnt = dif_str(s, &tm1b, &tm2b); write(1, s, scnt); write(1, buf, cnt); memcpy(&tm2b, &tm1b, sizeof(struct timeval)); } if (FD_ISSET(fd3, &testfds)) { cnt = read(fd3, buf, BUFSZ); if (cnt < 0) { perror("read failed"); break; } gettimeofday(&tm1c, NULL); scnt = dif_str(s, &tm1c, &tm2c); write(1, s, scnt); write(1, buf, cnt); memcpy(&tm2c, &tm1c, sizeof(struct timeval)); } } close(fd1); close(fd2); close(fd3); return 0; }

Task Execution List B- 0-16: Mailbox command exchange in task8

(mailbox commands) # ./test8 10 M->D, WDSND (task8a)

M->D, WDSND (task8b) M->D, WDSND (task8c)

time : 214.11 Hello from task8c! * D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.13 (+ 0.02) Hello from task8c! * D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.16 (+ 0.03) Hello from task8c! * D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 214.19 (+ 0.03) Hello from task8c! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.21 (+ 0.02) Hello from task8c! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.24 (+ 0.03) Hello from task8c! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.27 (+ 0.03) Hello from task8c! *

D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 214.29 (+ 0.02) Hello from task8c! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.32 (+ 0.03) Hello from task8c! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.34 (+ 0.02) Hello from task8c! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.40 Hello from task8b! * D->M, BKSND(BID=2)

Page 121: Linux DSP Gateway Specification - SourceForge

121 (126)

M->D, BKYLD(BID=0) time : 214.45 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.48 Hello from task8a! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.50 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.54 (+ 0.04) Hello from task8b! *

D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 214.59 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.62 (+ 0.14) Hello from task8a! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.64 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.72 (+ 0.08) Hello from task8b! *

D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 214.76 (+ 0.14) Hello from task8a! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.76 (+ 0.04) Hello from task8b! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 214.81 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 214.86 (+ 0.05) Hello from task8b! *

D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 214.88 (+ 0.12) Hello from task8a! *

D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 214.95 (+ 0.07) Hello from task8a! *

D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 215.02 (+ 0.07) Hello from task8a! *

D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

time : 215.09 (+ 0.07) Hello from task8a! * D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

time : 215.15 (+ 0.06) Hello from task8a! * D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

time : 215.22 (+ 0.07) Hello from task8a! * D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

time : 215.29 (+ 0.07) Hello from task8a! * D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

(^c) #

Page 122: Linux DSP Gateway Specification - SourceForge

122 (126)

8) hellotimer

Task Name: “hellotimer” Task Type: active block sending / passive word receiving The Timer1 Queue sample. This task receives 1-word data, which is the iteration count and sends the string “Hello from DSP!¥n” for iteration count times by the timer1 interval (1 second).

DSP Source Code List B- 0-17: DSP task example: hellotimer

/* * hellotimer.c */ #include <std.h> #include <sys.h> #include <mem.h> #include <sem.h> #include <tsk.h> #include "tokliBIOS.h" struct ht_udata { Int cnt; SEM_Handle sem_timer; TSK_Handle tsk; Void *tq_id; }; static Int strcpy16to8(Char *d, Char *s) { Int cnt = 0; for (; *s; s++, d++) { *d = *s; *d |= *++s << 8; cnt++; if (!*s) return cnt; } *d = '¥0'; return cnt; } static Uns ht_callback(struct dsptask *task) { struct ht_udata *udata = (struct ht_udata *)task->udata; SEM_post(udata->sem_timer); return 0; } static Void hello_timer(Arg task_arg) { struct dsptask *task = ArgToPtr(task_arg); struct ht_udata *udata = (struct ht_udata *)task->udata; Uns bid; Int cnt; TSK_setpri(TSK_self(), DSPTASK_DEFAULT_PRIORITY); for (;;) { SEM_pend(udata->sem_timer, SYS_FOREVER);

Page 123: Linux DSP Gateway Specification - SourceForge

123 (126)

dbg(task, "ht_loop(): udata->cnt = %d¥n", udata->cnt); bid = get_free_ipbuf(task); if (bid == MBCMD_BID_NULL) { cmderr(task, MBCMD_EID_STVBUF); unregister_tq_1s(task, udata->tq_id); } cnt = strcpy16to8((Char *)ipbuf_d[bid], "Hello from DSP!¥n"); bksnd(task, bid, cnt); if (--udata->cnt == 0) unregister_tq_1s(task, udata->tq_id); } } static Void init_obj(struct dsptask *task) { struct ht_udata *udata = (struct ht_udata *)task->udata; udata->cnt = 0; udata->sem_timer = NULL; udata->tsk = NULL; udata->tq_id = MEM_ILLEGAL; } static Void free_obj(struct dsptask *task) { struct ht_udata *udata = (struct ht_udata *)task->udata; Uns intm_saved; intm_saved = HWI_disable(); udata->cnt = 0; if (udata->tq_id != MEM_ILLEGAL) { unregister_tq_1s(task, udata->tq_id); udata->tq_id = MEM_ILLEGAL; } if (udata->tsk != NULL) { TSK_delete(udata->tsk); udata->tsk = NULL; } if (udata->sem_timer != NULL) { SEM_delete(udata->sem_timer); udata->sem_timer = NULL; } HWI_restore(intm_saved); } static Uns ht_rcv_wdsnd(struct dsptask *task, Uns data) { struct ht_udata *udata = (struct ht_udata *)task->udata; free_obj(task); udata->cnt = data; udata->sem_timer = SEM_create(0, NULL); udata->tsk = TSK_create((Fxn)hello_timer, NULL, (Arg)task); udata->tq_id = register_tq_1s(task, ht_callback); if ((udata->sem_timer == NULL) || (udata->tsk == NULL) || (udata->tq_id == MEM_ILLEGAL)) { free_obj(task); return MBCMD_EID_NOMEM; } return 0; } static Uns ht_rcv_tctl(struct dsptask *task, Uns ctlcmd, Uns *ret, Uns arg) { switch (ctlcmd) { case MBCMD_TCTL_TINIT: init_obj(task);

Page 124: Linux DSP Gateway Specification - SourceForge

124 (126)

break; case MBCMD_TCTL_TCLR: free_obj(task); break; case 0x8001: /* stop */ dbg(task, "[DSP] hellotimer TCTL 8001: stop"); free_obj(task); break; default: return MBCMD_EID_BADTCTL; } return 0; } static struct ht_udata udata; #pragma DATA_SECTION(task_hellotimer, "dspgw_task") struct dsptask task_hellotimer = { TID_MAGIC, /* tid */ "hellotimer", /* name */ MBCMD_TTYP_GBDM | MBCMD_TTYP_BKDM | MBCMD_TTYP_WDMD | MBCMD_TTYP_ASND | MBCMD_TTYP_PRCV, /* ttyp: active block snd, passive word rcv */ ht_rcv_wdsnd, /* rcv_snd */ NULL, /* rcv_req */ ht_rcv_tctl, /* rcv_tctl */ NULL, /* tsk_attrs */ NULL, /* mmap_info */ &udata /* udata */ };

Linux Frontent Program List B- 0-18: Frontent program for hellotimer

/* * hellotimer.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/time.h> #undef DEBUG_PARTIAL_READ #ifdef DEBUG_PARTIAL_READ #define BUFSZ 6 #else #define BUFSZ 256 #endif void usage(char *cmd) { fprintf(stderr, "%s <repeat_count>¥n", cmd); } int main(int argc, char **argv)

Page 125: Linux DSP Gateway Specification - SourceForge

125 (126)

{ int fd; unsigned short repeat; #ifndef DEBUG_PARTIAL_READ unsigned short i; #endif char *devfn = "/dev/dsptask/hellotimer"; if (argc != 2) { usage(argv[0]); return 1; } repeat = atoi(argv[1]); fd = open(devfn, O_RDWR); if (fd < 0) { fprintf(stderr, "cannot open %s¥n", devfn); return 1; } write(fd, &repeat, 2); #ifdef DEBUG_PARTIAL_READ for (;;) { #else for (i = 0; i < repeat; i++) { #endif int cnt; char buf[BUFSZ]; struct timeval tm; char s[64]; int scnt; char lf = '¥n'; cnt = read(fd, buf, BUFSZ); if (cnt < 0) { perror("read failed"); break; } gettimeofday(&tm, NULL); scnt = sprintf(s, "time: %ld.%02ld ", tm.tv_sec, tm.tv_usec/10000); write(1, s, scnt); write(1, buf, cnt); write(1, &lf, 1); #ifdef DEBUG_PARTIAL_READ { int j; for (j = 0; j < 20; j++) { usleep(1000); } } #endif } ioctl(fd, 0x8001); /* stop */ close(fd); return 0; }

Task Execution List B- 0-19: Mailbox command exchange in hellotimer

(mailbox commands) # ./hellotimer 5 M->D, WDSND

Page 126: Linux DSP Gateway Specification - SourceForge

126 (126)

(kernel message) ht_loop(): task_ht->cnt = 5 time: 54.46 Hello from DSP!

D->M, DBG D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

(kernel message) ht_loop(): task_ht->cnt = 4 time: 55.46 Hello from DSP!

D->M, DBG D->M, BKSND(BID=1) M->D, BKYLD(BID=3)

(kernel message) ht_loop(): task_ht->cnt = 3 time: 56.46 Hello from DSP!

D->M, DBG D->M, BKSND(BID=2) M->D, BKYLD(BID=0)

(kernel message) ht_loop(): task_ht->cnt = 2 time: 57.46 Hello from DSP!

D->M, DBG D->M, BKSND(BID=3) M->D, BKYLD(BID=1)

(kernel message) ht_loop(): task_ht->cnt = 1 time: 58.46 Hello from DSP!

D->M, DBG D->M, BKSND(BID=0) M->D, BKYLD(BID=2)

#