Permalink
Find file
797 lines (693 sloc) 24.6 KB
/*
* prussdrv.c
*
* User space driver for PRUSS
*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* ============================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
#include <prussdrv.h>
#include "__prussdrv.h"
#include <stdio.h>
#ifdef __DEBUG
#define DEBUG_PRINTF(FORMAT, ...) fprintf(stderr, FORMAT, ## __VA_ARGS__)
#else
#define DEBUG_PRINTF(FORMAT, ...)
#endif
#define PRUSS_UIO_PRAM_PATH_LEN 128
#define PRUSS_UIO_PARAM_VAL_LEN 20
#define HEXA_DECIMAL_BASE 16
static tprussdrv prussdrv;
int __prussdrv_memmap_init(void)
{
int i, fd;
char hexstring[PRUSS_UIO_PARAM_VAL_LEN];
if (prussdrv.mmap_fd == 0) {
for (i = 0; i < NUM_PRU_HOSTIRQS; i++) {
if (prussdrv.fd[i])
break;
}
if (i == NUM_PRU_HOSTIRQS)
return -1;
else
prussdrv.mmap_fd = prussdrv.fd[i];
}
fd = open(PRUSS_UIO_DRV_PRUSS_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.pruss_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_PRUSS_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.pruss_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.pru0_dataram_base =
mmap(0, prussdrv.pruss_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_PRUSS);
prussdrv.version =
__pruss_detect_hw_version(prussdrv.pru0_dataram_base);
switch (prussdrv.version) {
case PRUSS_V1:
{
DEBUG_PRINTF(PRUSS_V1_STR "\n");
prussdrv.pru0_dataram_phy_base = AM18XX_DATARAM0_PHYS_BASE;
prussdrv.pru1_dataram_phy_base = AM18XX_DATARAM1_PHYS_BASE;
prussdrv.intc_phy_base = AM18XX_INTC_PHYS_BASE;
prussdrv.pru0_control_phy_base = AM18XX_PRU0CONTROL_PHYS_BASE;
prussdrv.pru0_debug_phy_base = AM18XX_PRU0DEBUG_PHYS_BASE;
prussdrv.pru1_control_phy_base = AM18XX_PRU1CONTROL_PHYS_BASE;
prussdrv.pru1_debug_phy_base = AM18XX_PRU1DEBUG_PHYS_BASE;
prussdrv.pru0_iram_phy_base = AM18XX_PRU0IRAM_PHYS_BASE;
prussdrv.pru1_iram_phy_base = AM18XX_PRU1IRAM_PHYS_BASE;
}
break;
case PRUSS_V2:
{
DEBUG_PRINTF(PRUSS_V2_STR "\n");
prussdrv.pru0_dataram_phy_base = AM33XX_DATARAM0_PHYS_BASE;
prussdrv.pru1_dataram_phy_base = AM33XX_DATARAM1_PHYS_BASE;
prussdrv.intc_phy_base = AM33XX_INTC_PHYS_BASE;
prussdrv.pru0_control_phy_base = AM33XX_PRU0CONTROL_PHYS_BASE;
prussdrv.pru0_debug_phy_base = AM33XX_PRU0DEBUG_PHYS_BASE;
prussdrv.pru1_control_phy_base = AM33XX_PRU1CONTROL_PHYS_BASE;
prussdrv.pru1_debug_phy_base = AM33XX_PRU1DEBUG_PHYS_BASE;
prussdrv.pru0_iram_phy_base = AM33XX_PRU0IRAM_PHYS_BASE;
prussdrv.pru1_iram_phy_base = AM33XX_PRU1IRAM_PHYS_BASE;
prussdrv.pruss_sharedram_phy_base =
AM33XX_PRUSS_SHAREDRAM_BASE;
prussdrv.pruss_cfg_phy_base = AM33XX_PRUSS_CFG_BASE;
prussdrv.pruss_uart_phy_base = AM33XX_PRUSS_UART_BASE;
prussdrv.pruss_iep_phy_base = AM33XX_PRUSS_IEP_BASE;
prussdrv.pruss_ecap_phy_base = AM33XX_PRUSS_ECAP_BASE;
prussdrv.pruss_miirt_phy_base = AM33XX_PRUSS_MIIRT_BASE;
prussdrv.pruss_mdio_phy_base = AM33XX_PRUSS_MDIO_BASE;
}
break;
default:
DEBUG_PRINTF(PRUSS_UNKNOWN_STR "\n");
}
prussdrv.pru1_dataram_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_dataram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.intc_base =
prussdrv.pru0_dataram_base + prussdrv.intc_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_control_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_control_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_debug_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_debug_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_control_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_control_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_debug_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_debug_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_iram_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_iram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_iram_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_iram_phy_base -
prussdrv.pru0_dataram_phy_base;
if (prussdrv.version == PRUSS_V2) {
prussdrv.pruss_sharedram_base =
prussdrv.pru0_dataram_base +
prussdrv.pruss_sharedram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_cfg_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_cfg_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_uart_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_uart_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_iep_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_iep_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_ecap_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_ecap_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_miirt_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_miirt_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_mdio_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_mdio_phy_base -
prussdrv.pru0_dataram_phy_base;
}
#ifndef DISABLE_L3RAM_SUPPORT
fd = open(PRUSS_UIO_DRV_L3RAM_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.l3ram_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_L3RAM_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.l3ram_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.l3ram_base =
mmap(0, prussdrv.l3ram_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_L3RAM);
#endif
fd = open(PRUSS_UIO_DRV_EXTRAM_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.extram_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_EXTRAM_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.extram_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.extram_base =
mmap(0, prussdrv.extram_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_EXTRAM);
return 0;
}
int prussdrv_init(void)
{
memset(&prussdrv, 0, sizeof(prussdrv));
return 0;
}
int prussdrv_open(unsigned int host_interrupt)
{
char name[PRUSS_UIO_PRAM_PATH_LEN];
if (!prussdrv.fd[host_interrupt]) {
sprintf(name, "/dev/uio%d", host_interrupt);
prussdrv.fd[host_interrupt] = open(name, O_RDWR | O_SYNC);
if (prussdrv.fd[host_interrupt] == -1) {
return -1;
}
return __prussdrv_memmap_init();
} else {
return -1;
}
}
int prussdrv_version() {
return prussdrv.version;
}
const char * prussdrv_strversion(int version) {
switch (version) {
case PRUSS_V1:
return PRUSS_V1_STR;
case PRUSS_V2:
return PRUSS_V2_STR;
default:
return PRUSS_UNKNOWN_STR;
}
}
int prussdrv_pru_reset(unsigned int prunum)
{
unsigned int *prucontrolregs;
if (prunum == 0)
prucontrolregs = (unsigned int *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (unsigned int *) prussdrv.pru1_control_base;
else
return -1;
*prucontrolregs = 0;
return 0;
}
int prussdrv_pru_enable(unsigned int prunum)
{
return prussdrv_pru_enable_at(prunum, 0);
}
int prussdrv_pru_enable_at(unsigned int prunum, size_t addr)
{
volatile uint32_t* prucontrolregs;
if (prunum == 0)
prucontrolregs = (volatile uint32_t *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (volatile uint32_t *) prussdrv.pru1_control_base;
else
return -1;
/* address is in bytes and must be converted in 32 bits words */
*prucontrolregs = ((uint32_t)(addr / sizeof(uint32_t)) << 16) | 2;
return 0;
}
int prussdrv_pru_disable(unsigned int prunum)
{
unsigned int *prucontrolregs;
if (prunum == 0)
prucontrolregs = (unsigned int *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (unsigned int *) prussdrv.pru1_control_base;
else
return -1;
*prucontrolregs = 1;
return 0;
}
int prussdrv_pru_write_memory(unsigned int pru_ram_id,
unsigned int wordoffset,
const unsigned int *memarea,
unsigned int bytelength)
{
unsigned int *pruramarea, i, wordlength;
switch (pru_ram_id) {
case PRUSS0_PRU0_IRAM:
pruramarea = (unsigned int *) prussdrv.pru0_iram_base;
break;
case PRUSS0_PRU1_IRAM:
pruramarea = (unsigned int *) prussdrv.pru1_iram_base;
break;
case PRUSS0_PRU0_DATARAM:
pruramarea = (unsigned int *) prussdrv.pru0_dataram_base;
break;
case PRUSS0_PRU1_DATARAM:
pruramarea = (unsigned int *) prussdrv.pru1_dataram_base;
break;
case PRUSS0_SHARED_DATARAM:
if (prussdrv.version != PRUSS_V2)
return -1;
pruramarea = (unsigned int *) prussdrv.pruss_sharedram_base;
break;
default:
return -1;
}
wordlength = (bytelength + 3) >> 2; //Adjust length as multiple of 4 bytes
for (i = 0; i < wordlength; i++) {
*(pruramarea + i + wordoffset) = *(memarea + i);
}
return wordlength;
}
int prussdrv_pruintc_init(const tpruss_intc_initdata *prussintc_init_data)
{
volatile unsigned int *pruintc_io = (volatile unsigned int *) prussdrv.intc_base;
unsigned int i, mask1, mask2;
pruintc_io[PRU_INTC_SIPR1_REG >> 2] = 0xFFFFFFFF;
pruintc_io[PRU_INTC_SIPR2_REG >> 2] = 0xFFFFFFFF;
for (i = 0; i < (NUM_PRU_SYS_EVTS + 3) >> 2; i++)
pruintc_io[(PRU_INTC_CMR1_REG >> 2) + i] = 0;
for (i = 0;
((prussintc_init_data->sysevt_to_channel_map[i].sysevt != -1)
&& (prussintc_init_data->sysevt_to_channel_map[i].channel !=
-1)); i++) {
__prussintc_set_cmr(pruintc_io,
prussintc_init_data->sysevt_to_channel_map[i].
sysevt,
prussintc_init_data->sysevt_to_channel_map[i].
channel);
}
for (i = 0; i < (NUM_PRU_HOSTS + 3) >> 2; i++)
pruintc_io[(PRU_INTC_HMR1_REG >> 2) + i] = 0;
for (i = 0;
((prussintc_init_data->channel_to_host_map[i].channel != -1)
&& (prussintc_init_data->channel_to_host_map[i].host != -1));
i++) {
__prussintc_set_hmr(pruintc_io,
prussintc_init_data->channel_to_host_map[i].
channel,
prussintc_init_data->channel_to_host_map[i].
host);
}
pruintc_io[PRU_INTC_SITR1_REG >> 2] = 0x0;
pruintc_io[PRU_INTC_SITR2_REG >> 2] = 0x0;
mask1 = mask2 = 0;
for (i = 0; prussintc_init_data->sysevts_enabled[i] != 255; i++) {
if (prussintc_init_data->sysevts_enabled[i] < 32) {
mask1 =
mask1 + (1 << (prussintc_init_data->sysevts_enabled[i]));
} else if (prussintc_init_data->sysevts_enabled[i] < 64) {
mask2 =
mask2 +
(1 << (prussintc_init_data->sysevts_enabled[i] - 32));
} else {
DEBUG_PRINTF("Error: SYS_EVT%d out of range\n",
prussintc_init_data->sysevts_enabled[i]);
return -1;
}
}
pruintc_io[PRU_INTC_ESR1_REG >> 2] = mask1;
pruintc_io[PRU_INTC_SECR1_REG >> 2] = mask1;
pruintc_io[PRU_INTC_ESR2_REG >> 2] = mask2;
pruintc_io[PRU_INTC_SECR2_REG >> 2] = mask2;
for (i = 0; i < MAX_HOSTS_SUPPORTED; i++)
if (prussintc_init_data->host_enable_bitmask & (1 << i)) {
pruintc_io[PRU_INTC_HIEISR_REG >> 2] = i;
}
pruintc_io[PRU_INTC_GER_REG >> 2] = 0x1;
// Stash a copy of the intc settings
memcpy( &prussdrv.intc_data, prussintc_init_data,
sizeof(prussdrv.intc_data) );
return 0;
}
short prussdrv_get_event_to_channel_map( unsigned int eventnum )
{
unsigned int i;
for (i = 0; i < NUM_PRU_SYS_EVTS &&
prussdrv.intc_data.sysevt_to_channel_map[i].sysevt !=-1 &&
prussdrv.intc_data.sysevt_to_channel_map[i].channel !=-1; ++i) {
if ( eventnum == prussdrv.intc_data.sysevt_to_channel_map[i].sysevt )
return prussdrv.intc_data.sysevt_to_channel_map[i].channel;
}
return -1;
}
short prussdrv_get_channel_to_host_map( unsigned int channel )
{
unsigned int i;
for (i = 0; i < NUM_PRU_CHANNELS &&
prussdrv.intc_data.channel_to_host_map[i].channel != -1 &&
prussdrv.intc_data.channel_to_host_map[i].host != -1; ++i) {
if ( channel == prussdrv.intc_data.channel_to_host_map[i].channel )
/** -2 is because first two host interrupts are reserved
* for PRU0 and PRU1 */
return prussdrv.intc_data.channel_to_host_map[i].host - 2;
}
return -1;
}
short prussdrv_get_event_to_host_map( unsigned int eventnum )
{
short ans = prussdrv_get_event_to_channel_map( eventnum );
if (ans < 0) return ans;
return prussdrv_get_channel_to_host_map( ans );
}
int prussdrv_pru_send_event(unsigned int eventnum)
{
volatile unsigned int *pruintc_io = (volatile unsigned int *) prussdrv.intc_base;
if (eventnum < 32)
pruintc_io[PRU_INTC_SRSR1_REG >> 2] = 1 << eventnum;
else
pruintc_io[PRU_INTC_SRSR2_REG >> 2] = 1 << (eventnum - 32);
return 0;
}
unsigned int prussdrv_pru_wait_event(unsigned int host_interrupt)
{
unsigned int event_count;
read(prussdrv.fd[host_interrupt], &event_count, sizeof(int));
return event_count;
}
int prussdrv_pru_event_fd(unsigned int host_interrupt)
{
if (host_interrupt < NUM_PRU_HOSTIRQS)
return prussdrv.fd[host_interrupt];
else
return -1;
}
int prussdrv_pru_clear_event(unsigned int host_interrupt, unsigned int sysevent)
{
volatile unsigned int *pruintc_io = (volatile unsigned int *) prussdrv.intc_base;
if (sysevent < 32)
pruintc_io[PRU_INTC_SECR1_REG >> 2] = 1 << sysevent;
else
pruintc_io[PRU_INTC_SECR2_REG >> 2] = 1 << (sysevent - 32);
// Re-enable the host interrupt. Note that we must do this _after_ the
// system event has been cleared so as to not re-tigger the interrupt line.
// See Section 6.4.9 of Reference manual about HIEISR register.
// The +2 is because the first two host interrupts are reserved for
// PRU0 and PRU1.
pruintc_io[PRU_INTC_HIEISR_REG >> 2] = host_interrupt+2;
return 0;
}
int prussdrv_pru_send_wait_clear_event(unsigned int send_eventnum,
unsigned int host_interrupt,
unsigned int ack_eventnum)
{
prussdrv_pru_send_event(send_eventnum);
prussdrv_pru_wait_event(host_interrupt);
prussdrv_pru_clear_event(host_interrupt, ack_eventnum);
return 0;
}
int prussdrv_map_l3mem(void **address)
{
*address = prussdrv.l3ram_base;
return 0;
}
int prussdrv_map_extmem(void **address)
{
*address = prussdrv.extram_base;
return 0;
}
unsigned int prussdrv_extmem_size(void)
{
return prussdrv.extram_map_size;
}
int prussdrv_map_prumem(unsigned int pru_ram_id, void **address)
{
switch (pru_ram_id) {
case PRUSS0_PRU0_DATARAM:
*address = prussdrv.pru0_dataram_base;
break;
case PRUSS0_PRU1_DATARAM:
*address = prussdrv.pru1_dataram_base;
break;
case PRUSS0_SHARED_DATARAM:
if (prussdrv.version != PRUSS_V2)
return -1;
*address = prussdrv.pruss_sharedram_base;
break;
default:
*address = 0;
return -1;
}
return 0;
}
int prussdrv_map_peripheral_io(unsigned int per_id, void **address)
{
if (prussdrv.version != PRUSS_V2)
return -1;
switch (per_id) {
case PRUSS0_CFG:
*address = prussdrv.pruss_cfg_base;
break;
case PRUSS0_UART:
*address = prussdrv.pruss_uart_base;
break;
case PRUSS0_IEP:
*address = prussdrv.pruss_iep_base;
break;
case PRUSS0_ECAP:
*address = prussdrv.pruss_ecap_base;
break;
case PRUSS0_MII_RT:
*address = prussdrv.pruss_miirt_base;
break;
case PRUSS0_MDIO:
*address = prussdrv.pruss_mdio_base;
break;
default:
*address = 0;
return -1;
}
return 0;
}
unsigned int prussdrv_get_phys_addr(const void *address)
{
unsigned int retaddr = 0;
if ((address >= prussdrv.pru0_dataram_base)
&& (address <
prussdrv.pru0_dataram_base + prussdrv.pruss_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.pru0_dataram_base) +
prussdrv.pru0_dataram_phy_base);
} else if ((address >= prussdrv.l3ram_base)
&& (address <
prussdrv.l3ram_base + prussdrv.l3ram_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.l3ram_base) +
prussdrv.l3ram_phys_base);
} else if ((address >= prussdrv.extram_base)
&& (address <
prussdrv.extram_base + prussdrv.extram_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.extram_base) +
prussdrv.extram_phys_base);
}
return retaddr;
}
void *prussdrv_get_virt_addr(unsigned int phyaddr)
{
void *address = 0;
if ((phyaddr >= prussdrv.pru0_dataram_phy_base)
&& (phyaddr <
prussdrv.pru0_dataram_phy_base + prussdrv.pruss_map_size)) {
address =
(void *) ((unsigned int) prussdrv.pru0_dataram_base +
(phyaddr - prussdrv.pru0_dataram_phy_base));
} else if ((phyaddr >= prussdrv.l3ram_phys_base)
&& (phyaddr <
prussdrv.l3ram_phys_base + prussdrv.l3ram_map_size)) {
address =
(void *) ((unsigned int) prussdrv.l3ram_base +
(phyaddr - prussdrv.l3ram_phys_base));
} else if ((phyaddr >= prussdrv.extram_phys_base)
&& (phyaddr <
prussdrv.extram_phys_base + prussdrv.extram_map_size)) {
address =
(void *) ((unsigned int) prussdrv.extram_base +
(phyaddr - prussdrv.extram_phys_base));
}
return address;
}
int prussdrv_exit()
{
int i;
munmap(prussdrv.pru0_dataram_base, prussdrv.pruss_map_size);
munmap(prussdrv.l3ram_base, prussdrv.l3ram_map_size);
munmap(prussdrv.extram_base, prussdrv.extram_map_size);
for (i = 0; i < NUM_PRU_HOSTIRQS; i++) {
if (prussdrv.fd[i])
close(prussdrv.fd[i]);
}
return 0;
}
int prussdrv_exec_program(int prunum, const char *filename)
{
return prussdrv_exec_program_at(prunum, filename, 0);
}
int prussdrv_exec_program_at(int prunum, const char *filename, size_t addr)
{
FILE *fPtr;
unsigned char fileDataArray[PRUSS_MAX_IRAM_SIZE];
int fileSize = 0;
// Open an File from the hard drive
fPtr = fopen(filename, "rb");
if (fPtr == NULL) {
DEBUG_PRINTF("File %s open failed\n", filename);
return -1;
} else {
DEBUG_PRINTF("File %s open passed\n", filename);
}
// Read file size
fseek(fPtr, 0, SEEK_END);
fileSize = ftell(fPtr);
if (fileSize == 0) {
DEBUG_PRINTF("File read failed.. Closing program\n");
fclose(fPtr);
return -1;
}
if (fileSize > PRUSS_MAX_IRAM_SIZE) {
DEBUG_PRINTF("File too large.. Closing program\n");
fclose(fPtr);
return -1;
}
fseek(fPtr, 0, SEEK_SET);
if (fileSize !=
fread((unsigned char *) fileDataArray, 1, fileSize, fPtr)) {
DEBUG_PRINTF("WARNING: File Size mismatch\n");
fclose(fPtr);
return -1;
}
fclose(fPtr);
return prussdrv_exec_code_at(prunum, (const unsigned int *) fileDataArray, fileSize, addr);
}
int prussdrv_exec_code(int prunum, const unsigned int *code, int codelen)
{
return prussdrv_exec_code_at(prunum, code, codelen, 0);
}
int prussdrv_exec_code_at(int prunum, const unsigned int *code, int codelen, size_t addr)
{
unsigned int pru_ram_id;
if (prunum == 0)
pru_ram_id = PRUSS0_PRU0_IRAM;
else if (prunum == 1)
pru_ram_id = PRUSS0_PRU1_IRAM;
else
return -1;
// Make sure PRU sub system is first disabled/reset
prussdrv_pru_disable(prunum);
prussdrv_pru_write_memory(pru_ram_id, 0, code, codelen);
prussdrv_pru_enable_at(prunum, addr);
return 0;
}
int prussdrv_load_datafile(int prunum, const char *filename)
{
FILE *fPtr;
unsigned char fileDataArray[PRUSS_MAX_IRAM_SIZE];
int fileSize = 0;
// Open an File from the hard drive
fPtr = fopen(filename, "rb");
if (fPtr == NULL) {
DEBUG_PRINTF("File %s open failed\n", filename);
return -1;
} else {
DEBUG_PRINTF("File %s open passed\n", filename);
}
// Read file size
fseek(fPtr, 0, SEEK_END);
fileSize = ftell(fPtr);
if (fileSize == 0) {
DEBUG_PRINTF("File read failed.. Closing program\n");
fclose(fPtr);
return -1;
}
fseek(fPtr, 0, SEEK_SET);
if (fileSize !=
fread((unsigned char *) fileDataArray, 1, fileSize, fPtr)) {
DEBUG_PRINTF("WARNING: File Size mismatch\n");
fclose(fPtr);
return -1;
}
fclose(fPtr);
return prussdrv_load_data(prunum, (const unsigned int *) fileDataArray, fileSize);
}
int prussdrv_load_data(int prunum, const unsigned int *code, int codelen)
{
unsigned int pru_ram_id;
if (prunum == 0)
pru_ram_id = PRUSS0_PRU0_DATARAM;
else if (prunum == 1)
pru_ram_id = PRUSS0_PRU1_DATARAM;
else
return -1;
// Make sure PRU sub system is first disabled/reset
prussdrv_pru_disable(prunum);
prussdrv_pru_write_memory(pru_ram_id, 0, code, codelen);
//prussdrv_pru_enable(prunum);
return 0;
}