Branch "uflash" imported from GoogleCode.

This commit is contained in:
Sergey
2015-03-21 14:11:41 -07:00
parent 7e4b86d135
commit 163dcbd961
457 changed files with 146252 additions and 4193 deletions
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)gpio.h 1.4 (2.11BSD GTE) 1997/3/28
*/
/*
* Ioctl definitions
*/
#ifndef _UFLASH_H
#define _UFLASH_H
#include <sys/ioctl.h>
#include <sys/uio.h>
#define UFLASH_LOAD (IOC_VOID | 1 << 16 | 'u'<<8) /* configure as input */
#define UFLASH_MAGIC 0x24
struct uflash_head
{
unsigned magic;
char name[31];
};
#define UFLASH_HEADPTR ((struct uflash_head*)0x7d030000)
typedef void (*_startp)(int, char **, char **);
#define UFLASH_STARTPTR ((_startp)0x7d030030)
#ifdef KERNEL
int uflash_open (dev_t dev, int flag, int mode);
int uflash_close (dev_t dev, int flag, int mode);
int uflash_read (dev_t dev, struct uio *uio, int flag);
int uflash_write (dev_t dev, struct uio *uio, int flag);
int uflash_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag);
#endif
#endif
+1 -1
View File
@@ -2,7 +2,7 @@
# Programs that live in subdirectories, and have makefiles of their own.
#
SUBDIR = baremetal dip duinomite explorer16 max32 max32-eth maximite meb \
pinguino-micro starter-kit ubw32 ubw32-uart ubw32-uart-sdramswap usbboot
pinguino-micro starter-kit ubw32 ubw32-uart usbboot
default:
+1 -1
View File
@@ -62,8 +62,8 @@ int adc_open(dev_t dev, int flag, int mode)
AD1CON2 = 0b0000010000111100;
AD1CON3 = 0b0000011100000111;
AD1CON1 = 0b1000000011100110;
IPC(6) = 0b00000100000000000000000000000000;
IECSET(1) = 1<<(PIC32_IRQ_AD1-32);
IPC(6) = 0x04040404;
}
nactive++;
return 0;
+7 -1
View File
@@ -37,7 +37,13 @@ DEFS += -DLED_AUX_PORT=TRISG -DLED_AUX_PIN=13
DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
DRIVER_ADC = yes
DRIVER_OC = yes
DRIVER_GLCD = yes
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
+26
View File
@@ -14,6 +14,7 @@
#include "clist.h"
#include "tty.h"
#include "systm.h"
#include "errno.h"
#ifdef GPIO_ENABLED
#include "gpio.h"
@@ -35,6 +36,10 @@
#include "oc.h"
#endif
#ifdef UFLASH_ENABLED
#include "uflash.h"
#endif
#ifndef SWAPDEV
#define swopen nulldev
#define swstrategy nostrategy
@@ -50,6 +55,14 @@ nulldev ()
return (0);
}
#ifndef UFLASH_ENABLED
static int
faildev ()
{
return (EPERM);
}
#endif
static int
norw (dev, uio, flag)
dev_t dev;
@@ -179,6 +192,19 @@ const struct cdevsw cdevsw[] = {
nostrategy, },
#endif
// UFLASH = 12
#ifdef UFLASH_ENABLED
{
uflash_open, uflash_close, uflash_read, uflash_write,
uflash_ioctl, nulldev, 0, seltrue,
nostrategy, },
#else
{
faildev, nulldev, norw, norw,
noioctl, nulldev, 0, seltrue,
nostrategy, },
#endif
};
const int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+3
View File
@@ -41,6 +41,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+5
View File
@@ -3,6 +3,11 @@ ifeq ($(DRIVER_GPIO),yes)
DEFS += -DGPIO_ENABLED
endif
ifeq ($(DRIVER_UFLASH),yes)
KERNOBJ += uflash.o
DEFS += -DUFLASH_ENABLED
endif
ifeq ($(DRIVER_POWER),yes)
KERNOBJ += power_control.o
POWER_LED_PORT ?= TRISG
+3
View File
@@ -51,6 +51,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -53,6 +53,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -39,6 +39,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+7 -4
View File
@@ -30,10 +30,13 @@ DEFS += -DSD_CS0_PORT=TRISG -DSD_CS0_PIN=9
DEFS += -DLED_KERNEL_PORT=TRISE -DLED_KERNEL_PIN=5
# Include or exclude drivers
DRIVER_GPIO = yes # General Purpose I/O
DRIVER_ADC = yes # Basic ADC interface
DRIVER_SPI = yes # Generic SPI interface
DRIVER_OC = yes # Output Compare driver
DRIVER_GPIO = yes
DRIVER_ADC = yes
DRIVER_SPI = yes
DRIVER_OC = yes
# Support userland program in flash
DRIVER_UFLASH = no
DEPFLAGS = -MT $@ -MD -MP -MF .deps/$*.dep
CFLAGS = -O $(DEFS) $(DEPFLAGS)
+5 -30
View File
@@ -134,17 +134,9 @@ startup()
mips_write_c0_register (C0_CAUSE, 0, CA_IV);
/* Setup memory. */
BMXPUPBA = 512 << 10; /* Kernel Flash memory size */
#ifdef KERNEL_EXECUTABLE_RAM
extern void _keram_start(), _keram_end();
unsigned keram_size_k = ((char*)&_keram_end-(char*)&_keram_start)/1024;
BMXDKPBA = (32-keram_size_k) << 10; /* Kernel RAM size */
BMXDUDBA = BMXDKPBA+(keram_size_k<<10); /* 2k executable RAM in kernel */
#else
BMXPUPBA = 192 << 10; /* Kernel Flash memory size */
BMXDKPBA = 32 << 10; /* Kernel RAM size */
BMXDUDBA = BMXDKPBA; /* Zero executable RAM in kernel */
#endif
BMXDUDBA = BMXDKPBA; /* No executable RAM in kernel */
BMXDUPBA = BMXDUDBA; /* All user RAM is executable */
/*
@@ -159,7 +151,9 @@ startup()
IPC(8) = IPC(9) = IPC(10) = IPC(11) =
IPC(12) =
PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) |
PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1);
PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) |
PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) |
PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ;
/*
* Setup wait states.
@@ -243,25 +237,6 @@ startup()
/*printf ("copy %08x from (%08x) to (%08x)\n", *src, src, dest);*/
*dest++ = *src++;
}
#ifdef KERNEL_EXECUTABLE_RAM
/* Copy code that must run out of ram (due to timing restrictions)
* from flash to the executable section of kernel ram.
* This was added to support swap on sdram */
extern void _ramfunc_image_begin();
extern void _ramfunc_begin();
extern void _ramfunc_end();
unsigned *src1 = (unsigned*) &_ramfunc_image_begin;
unsigned *dest1 = (unsigned*)&_ramfunc_begin;
unsigned *limit1 = (unsigned*)&_ramfunc_end;
/*printf ("copy from (%08x) to (%08x)\n", src1, dest1);*/
while (dest1 < limit1) {
*dest1++ = *src1++;
}
#endif
#endif
/*
* Setup UART registers.
-11
View File
@@ -63,12 +63,7 @@
#define DATA_SIZE (128*1024)
#define KERNEL_FLASH_SIZE (192*1024)
#ifdef KERNEL_EXECUTABLE_RAM
#define KERNEL_DATA_SIZE (30*1024)
#else
#define KERNEL_DATA_SIZE (32*1024)
#endif
#define KERNEL_FLASH_START 0x9d000000
#define USER_FLASH_START (KERNEL_FLASH_START + KERNEL_FLASH_SIZE)
@@ -76,13 +71,7 @@
#define KERNEL_DATA_START 0x80000000
#define KERNEL_DATA_END (KERNEL_DATA_START + KERNEL_DATA_SIZE)
#ifdef KERNEL_EXECUTABLE_RAM
#define USER_DATA_START (0x7f000000 + KERNEL_DATA_SIZE+2048)
#else
#define USER_DATA_START (0x7f000000 + KERNEL_DATA_SIZE)
#endif
#define USER_DATA_END (0x7f000000 + DATA_SIZE)
#define stacktop(siz) (USER_DATA_END)
+3
View File
@@ -47,6 +47,9 @@ DRIVER_SPI = yes
# Basic ADC interface
DRIVER_ADC = yes
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+5 -2
View File
@@ -42,10 +42,13 @@ DEFS += -DLED_TTY_PORT=TRISA -DLED_TTY_PIN=3
# Include or exclude drivers
# General Purpose I/O
DRIVER_GPIO = yes
DRIVER_GPIO = no
# Basic ADC interface
DRIVER_ADC = yes
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = yes
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
+3
View File
@@ -50,6 +50,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -55,6 +55,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -48,6 +48,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = yes
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -40,6 +40,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = yes
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
-735
View File
@@ -1,735 +0,0 @@
/*
* SDRAM Access Routines for PIC32.
*
* Retromaster - 10.05.2010
*
* This file is in the public domain. You can use, modify, and distribute the source code
* and executable programs based on the source code. This file is provided "as is" and
* without any express or implied warranties whatsoever. Use at your own risk!
*
* Changes by madscifi for inclusion in the retrobsd project.
*/
/* SDRAM Pin to PIC32 Pin Mapping:
* SDRAM PIC32
* ------ ------
* notes, the order of An to RBn DOES matter
* At the moment it is a bit of a mess and
* needs to be cleaned up.
* A0 23 RB11
* A1 24 RB12
* A2 25 RB13
* A3 26 RB14
* A4 29 RB5
* A5 30 RB4
* A6 31 RB3
* A7 32 RB2
* A8 33 RB6
* A9 34 RB7
* A10 22? RB15
* A11 35 RB9
* BA0 20 RD15
* BA1 21 RD14
*
* note, the order of DQn to RAn does not matter
* DQ0 2 RA6
* DQ1 4 RA1
* DQ2 5 RA7
* DQ3 7 RA2
* DQ4 8 RA3
* DQ5 10 RA4
* DQ6 11 RA5
* DQ7 13 RA0
* CLK 38 OC4-RD3
* CKE 37 A10
* CS 19 RF4
* WE 16 RF0
* CAS 17 RF1
* RAS 18 RF5
*
* SDRam 42, 44, 45, 47, 48, 50, 51, 53 - pullup (d8-d15)
*/
/*
* Retrobsd does not currently contain a good header
* for pulling the pic32 port addresses into an assembly
* file, so define some needed registers here for the moment.
*/
#define TRISA 0xBF886000
#define T2CON 0xBF800800
#define TMR2 0xBF800810
#define PR2 0xBF800820
#define T2CONSET 0xBF800808
#define OC4CON 0xBF803600
#define OC4RS 0xBF803620
#define OC4R 0xBF803610
#define AD1PCFGSET 0xBF809068
/* Offsets (from TRISA) for the io ports */
#define SDR_OFFSET_A 0
#define SDR_OFFSET_B 0x40
#define SDR_OFFSET_C 0x80
#define SDR_OFFSET_D 0xc0
#define SDR_OFFSET_E 0x100
#define SDR_OFFSET_F 0x140
#define SDR_OFFSET_G 0x180
/* Offsets (from TRISA) for the various port control registers */
#define TRIS_OFFSET 0x0
#define PORT_OFFSET 0x10
#define LAT_OFFSET 0x20
#define ODCF_OFFSET 0x30
/* Offsets (from TRISA) for the various io port bit manipulator registers */
#define NOP_OP_OFFSET 0x0
#define CLR_OP_OFFSET 0x4
#define SET_OP_OFFSET 0x8
#define INV_OP_OFFSET 0xc
/*
* Specific assignments of ports ports used
* Note: In general, it is not sufficient to
* change the constants below - corresponding
* changes to the code below will likely be
* required if any of the following values
* are changed.
*/
/* DATA_PORT_TRIS must be assigned to a TRIS of the port
* that has the low 8 bits tied the 8 data bits on the ram.
*/
#define SDR_DATA_IO SDR_OFFSET_A
#define SDR_DATA_TRIS SDR_OFFSET_A
#define SDR_ADDRESS_IO SDR_OFFSET_B
#define SDR_ADDRESS_TRIS SDR_OFFSET_B
#define ADDRESS_MASK 0xfafc
#define SDR_BANK_IO SDR_OFFSET_D
#define SDR_BANK_TRIS SDR_OFFSET_D
#define BANK_0_BIT 14
#define BANK_1_BIT 15
#define SDR_CONTROL_IO SDR_OFFSET_F
#define SDR_CONTROL_TRIS SDR_OFFSET_F
#define CONTROL_WE_BIT 0
#define CONTROL_CAS_BIT 1
#define CONTROL_CS_BIT 4
#define CONTROL_RAS_BIT 5
#define SDR_CKE_IO SDR_OFFSET_A
#define SDR_CKE_TRIS SDR_OFFSET_A
#define CKE_BIT 10
#define CONTROL_ALL_MASK ( (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_CAS_BIT) | (1<<CONTROL_WE_BIT) )
#define BANK_ALL_MASK ( (1 << BANK_1_BIT) | ( 1 << BANK_0_BIT ) )
/* Global Symbols */
.globl sdram_init
.globl sdram_read
.globl sdram_write
.globl sdram_active
.globl sdram_auto_refresh
.globl sdram_precharge
.globl sdram_precharge_all
.globl sdram_sleep
.globl sdram_wake
.globl sdram_bank
.type sdram_init, @function
.type sdram_read, @function
.type sdram_write, @function
.type sdram_active, @function
.type sdram_auto_refresh, @function
.type sdram_precharge, @function
.type sdram_precharge_all, @function
.type sdram_sleep, @function
.type sdram_wake, @function
.type sdram_bank, @function
/*
* This code MUST execute from ram and the ram MUST be configured
* for zero wait states. Interrupts should be disabled before
* calling any of these functions, and any DMA should also be
* disabled.
*
* Also, the peripheral bus divisor must be set to 1.
*/
.section .ramfunc,"ax",@progbits
/* No instruction reordering */
.set noreorder
#define clock4 \
nop;nop;nop;nop
#define clock3 \
nop;nop;nop
#define clock2 \
nop;nop
#define clock1 \
nop
/*
* The SDRAM clock is output from the output compare unit.
* This macro synchronizes with that clock so that we are
* sure to have at least two clock cycles to issue control
* line changes and access the data bus before the rising
* edge.
*/
#define sync_clock \
la $t8, TMR2; \
li $v0, 2; \
lw $v1, ($t8); \
bge $v1, $v0, 1f; \
nop; \
nop; \
nop; \
1: \
nop;
#define output_column \
and $t5, $a0, 0x1f; \
sll $t5, 2; \
and $t6, $a0, 0x20; \
sll $t6, 9; \
or $t5, $t6; \
lw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0); \
and $t6, ~ADDRESS_MASK; \
or $t6, $t5; \
sw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0);
#define output_address \
sll $t5, $a0, 2; \
and $t5, ADDRESS_MASK; \
and $t6, $a0, 0x40; \
sll $t6, 8; \
or $t5, $t6; \
and $t6, $a0, 0x100; \
sll $t6, 7; \
or $t5, $t6; \
lw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0); \
and $t6, ~ADDRESS_MASK; \
or $t6, $t5; \
sw $t6, SDR_ADDRESS_TRIS + LAT_OFFSET($t0);
/*.ent sdram_init*/
/*
* Initializes the SDRAM.
* Should be called once sometime after startup
* C Prototype:
* extern __attribute__((far)) void sdram_init();
*/
sdram_init:
/* Initialize address lines */
la $t0, TRISA /* base of io addresses */
li $t1, ADDRESS_MASK
sw $t1, SDR_ADDRESS_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
li $t1, 0xFFFF
sw $t1, AD1PCFGSET
li $t1, BANK_ALL_MASK
sw $t1, SDR_BANK_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
/* All address lines low */
li $t1, ADDRESS_MASK
sw $t1, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
li $t1, BANK_ALL_MASK
sw $t1, SDR_BANK_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
/* Initialize data lines */
li $t1, 0xFF
sw $t1, SDR_DATA_IO + TRIS_OFFSET + SET_OP_OFFSET($t0)
/* Initialize SDRAM control lines */
li $t1, CONTROL_ALL_MASK
sw $t1, SDR_CONTROL_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
/* Command Inhibit */
li $t1, CONTROL_ALL_MASK
sw $t1, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
/* Initialize CKE line */
li $t1, (1<<CKE_BIT)
sw $t1, SDR_CKE_IO + TRIS_OFFSET + CLR_OP_OFFSET($t0)
/* CKE low */
li $t1, (1<<CKE_BIT)
sw $t1, SDR_CKE_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
/* SDRAM clock output */
/* Initialize Timer2 */
sw $zero, T2CON
sw $zero, TMR2
li $t1, 3
sw $t1, PR2
li $t1, 0x8000
sw $t1, T2CONSET
/* Initialize OC4 */
sw $zero, OC4CON
li $t1, 1
sw $t1, OC4RS
li $t1, 3
sw $t1, OC4R
li $t1, 0x8005
sw $t1, OC4CON
/* Clock output starts here */
/* SD-RAM initialization delay */
li $t2, 500
move $t1, $zero
sdram_init_delay_1:
addi $t1, $t1, 1
bne $t1, $t2, sdram_init_delay_1
nop
/* CKE high */
li $t1, (1<<CKE_BIT)
sw $t1, SDR_CKE_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
/* Delay some more */
li $t2, 3000
move $t1, $zero
sdram_init_delay_2:
addi $t1, $t1, 1
bne $t1, $t2, sdram_init_delay_2
nop
/* Get ready for the commands we are about to issue. */
li $t4, (1<<CONTROL_CAS_BIT)
li $t5, (1<<CONTROL_WE_BIT)
li $t6, 0x1810 /* Mode Register: CL:2, BL:8 (0x23) */
li $t7, CONTROL_ALL_MASK
li $t8, 0x8000 /* A10 */
sw $t8, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* A10 = 1 for Precharge ALL */
sync_clock
.set nomacro
/* Precharge All */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* LLLL */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* LLHL */
clock2
/* Auto Refresh 1 */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* LLLL */
sw $t5, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* LLLH */
clock2
/* Auto Refresh 2 */
clock4
/* Auto Refresh 3 */
clock4
/* Auto Refresh 4 */
clock4
/* Auto Refresh 5 */
clock4
/* Auto Refresh 6 */
clock4
/* Auto Refresh 7 */
clock4
/* Auto Refresh 8 */
li $t4, ADDRESS_MASK
sw $t4, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
clock2
/* Load Mode Register */
sw $t6, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + CLR_OP_OFFSET($t0)
clock2
/* Command Inhibit */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + SET_OP_OFFSET($t0)
clock3
/* Command Inhibit */
clock4
.set macro
jr $ra
nop
/*.end sdram_init*/
/*
* Sends ACTIVE command
* C Prototype:
* extern __attribute__((far)) void sdram_active(uint16_t rowaddr);
*/
sdram_active:
la $t0, TRISA /* Port Base */
li $t7, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)
/* Set row */
output_address
sync_clock
.set nomacro
/* Active */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0)
clock3
/* Command Inhibit */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0)
clock3
/* Command Inhibit */
clock4
.set macro
jr $ra
nop
/*
* Sends WRITE command
* C Prototype:
* extern __attribute__((far)) void sdram_write(uint16_t pseudocoladdr, uint64_t val);
* Each pseudo column contains 8 bytes of data (consists of 8 ram columns)
*/
sdram_write:
la $t0, TRISA /* Port Base */
li $t4, 0xFF
li $t7, (1<<CONTROL_CS_BIT) | (1<<CONTROL_CAS_BIT) | (1<<CONTROL_WE_BIT)
/* Set column */
output_column
/* Set data lines */
srl $t5, $a2, 24
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0)
sync_clock
.set nomacro
/* Write */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LHLL */
sw $t4, SDR_DATA_IO + TRIS_OFFSET + INV_OP_OFFSET($t0) /* 1 - enable data lines */
srl $t5, $a2, 16
clock1
/* Command Inhibit */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* HHHH */
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 2 */
srl $t5, $a2, 8
clock1
/* Command Inhibit */
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 3 */
clock3
/* Command Inhibit */
sb $a2, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 4 */
srl $t5, $a3, 24
clock2
/* Command Inhibit */
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 5 */
srl $t5, $a3, 16
clock2
/* Command Inhibit */
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 6 */
srl $t5, $a3, 8
clock2
/* Command Inhibit */
sb $t5, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 7 */
clock3
/* Command Inhibit */
sb $a3, SDR_DATA_IO + LAT_OFFSET + NOP_OP_OFFSET($t0) /* 8 */
clock3
sw $t4, SDR_DATA_IO + TRIS_OFFSET + INV_OP_OFFSET($t0) /* Data lines input again */
.set macro
jr $ra
nop
/*
* Sends READ command
* C Prototype:
* extern __attribute__((far)) uint64_t sdram_read(uint16_t pseudocoladdr);
* Each pseudo column contains 8 bytes of data (consists of 8 ram columns)
*/
sdram_read:
la $t0, TRISA /* Port Base */
li $t7, (1<<CONTROL_CS_BIT) | (1<<CONTROL_CAS_BIT)
/* Set column */
output_column
sync_clock
.set nomacro
/* Read */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LHLH */
clock3
/* Command Inhibit */
sw $t7, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* HHHH */
clock3
/* Command Inhibit */
clock3
lbu $v0, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 1 */
/* Command Inhibit */
clock3
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 2 */
/* Command Inhibit */
sll $v0, $v0, 8
or $v0, $v0, $t5
clock1
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 3 */
/* Command Inhibit */
sll $v0, $v0, 8
or $v0, $v0, $t5
clock1
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 4 */
/* Command Inhibit */
sll $v0, $v0, 8
or $v0, $v0, $t5
clock1
lbu $v1, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 5 */
/* Command Inhibit */
clock3
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 6 */
/* Command Inhibit */
sll $v1, $v1, 8
or $v1, $v1, $t5
clock1
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 7 */
/* Command Inhibit */
sll $v1, $v1, 8
or $v1, $v1, $t5
clock1
lbu $t5, SDR_DATA_IO + PORT_OFFSET + NOP_OP_OFFSET($t0) /* 8 */
/* Command Inhibit */
sll $v1, $v1, 8
or $v1, $v1, $t5
.set macro
jr $ra
nop
/*
* Sends PRECHARGE ALL command
* C Prototype:
* extern __attribute__((far)) void sdram_precharge_all(void);
*/
sdram_precharge_all:
la $t0, TRISA /* Port Base */
li $t3, 0x8000 /* A10 */
li $t4, (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_WE_BIT)
sw $t3, SDR_ADDRESS_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* A10 = 1 for Precharge ALL */
sync_clock
.set nomacro
/* Precharge All */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLHL */
clock3
/* Command Inhibit */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
clock3
.set macro
jr $ra
nop
/*
* Sends PRECHARGE command
* C Prototype:
* extern __attribute__((far)) void sdram_precharge(void);
*/
sdram_precharge:
la $t0, TRISA /* Port Base */
li $t3, 0x8000 /* A10 */
li $t4, (1<<CONTROL_CS_BIT) | (1<<CONTROL_RAS_BIT) | (1<<CONTROL_WE_BIT)
sw $t3, SDR_ADDRESS_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* A10 = 0 for Precharge */
sync_clock
.set nomacro
/* Precharge All */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLHL */
clock3
/* Command Inhibit */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
clock3
.set macro
jr $ra
nop
/*
* Sends AUTO REFRESH command
* All banks must be in PRECHARGEd state
* C Prototype:
* extern __attribute__((far)) void sdram_auto_refresh(void);
*/
sdram_auto_refresh:
la $t0, TRISA /* Port Base */
li $t4, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)|(1<<CONTROL_CAS_BIT)
sync_clock
.set nomacro
/* Auto Refresh */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLH */
clock3
/* Command Inhibit */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
clock3
.set macro
jr $ra
nop
/*
* Puts the SDRAM into the self refresh mode.
* SDRAM retains data in this state.
* C Prototype:
* extern __attribute__((far)) void sdram_sleep(void);
*/
sdram_sleep:
la $t0, TRISA /* Port Base */
li $t1, (1<<CKE_BIT)
li $t4, (1<<CONTROL_CS_BIT)|(1<<CONTROL_RAS_BIT)|(1<<CONTROL_CAS_BIT)
sync_clock
.set nomacro
/* Auto Refresh */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLH */
sw $t1, SDR_CKE_IO + LAT_OFFSET + CLR_OP_OFFSET($t0) /* CKE low */
clock2
/* Command Inhibit */
sw $t4, SDR_CONTROL_IO + LAT_OFFSET + INV_OP_OFFSET($t0) /* LLLL */
clock3
.set macro
jr $ra
nop
/*
* Takes the SDRAM out of the self refresh mode.
* Parameters: none
* C Prototype:
* extern __attribute__((far)) void sdram_wake(void);
*/
sdram_wake:
la $t0, TRISA /* Port Base */
li $t1, (1<<CKE_BIT)
sync_clock
.set nomacro
/* Command Inhibit */
sw $t1, SDR_CKE_IO + LAT_OFFSET + SET_OP_OFFSET($t0) /* CKE low */
clock3
/* Command Inhibit */
clock4
/* Command Inhibit */
clock4
.set macro
jr $ra
nop
/*
* Selects the bank to which commands are issued
* Parameters:
* C Prototype:
* extern __attribute__((far)) void sdram_bank(uint8_t bank);
* (only lower 2 bits are of bank are currently significant)
*/
sdram_bank:
la $t0, TRISA /* Port Base */
lw $t1, SDR_BANK_IO + LAT_OFFSET + NOP_OP_OFFSET($t0);
and $t1, ~BANK_ALL_MASK
sll $t2, $a0, BANK_0_BIT
or $t1, $t2
sw $t1, SDR_BANK_IO + LAT_OFFSET + NOP_OP_OFFSET($t0);
jr $ra
nop
-32
View File
@@ -1,32 +0,0 @@
/*
* SDRAM Access Routines for PIC32.
*
* Retromaster - 10.05.2010
*
* This file is in the public domain. You can use, modify, and distribute the source code
* and executable programs based on the source code. This file is provided "as is" and
* without any express or implied warranties whatsoever. Use at your own risk!
*
* Changes by madscifi for inclusion in the retrobsd project.
*/
#ifndef SDRAM_H
#define SDRAM_H
//#include <inttypes.h>
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef unsigned long long uint64_t;
extern __attribute__((far)) void sdram_init();
extern __attribute__((far)) void sdram_active(uint16_t rowaddr);
extern __attribute__((far)) void sdram_write(uint16_t pseudocoladdr, uint64_t val);
extern __attribute__((far)) uint64_t sdram_read(uint16_t pseudocoladdr);
extern __attribute__((far)) void sdram_auto_refresh(void);
extern __attribute__((far)) void sdram_precharge(void);
extern __attribute__((far)) void sdram_precharge_all(void);
extern __attribute__((far)) void sdram_sleep(void);
extern __attribute__((far)) void sdram_wake(void);
extern __attribute__((far)) void sdram_bank(uint8_t bank);
#endif
-221
View File
@@ -1,221 +0,0 @@
/*
* Driver for external SDRAM-based swap device.
*
* See sdram.S for information on interface to sdram
*
* This code could use a bit of optimization.
*/
#include "param.h"
#include "systm.h"
#include "buf.h"
#include "errno.h"
#include "dk.h"
#include "sdram.h"
int sw_dkn = -1; /* Statistics slot number */
/*
* physical specs of SDRAM chip
*/
#define RAM_COLS 512
#define RAM_ROWS 4096
#define RAM_BANKS 4
/*
* RAM_BURST_COUNT MUST be match the number of bytes
* read/written by each call to sdram_read/sdram_write
*/
#define RAM_BURST_COUNT 8
/*
* CHUNK_SIZE number of bytes in each "chunk"
*/
#define CHUNK_SIZE 128
#define RAM_BURST_GROUP_COUNT 8
#define BLOCKS_PER_ROW ( RAM_COLS / CHUNK_SIZE )
static char swaptemp[CHUNK_SIZE];
static void
read_chunk_from_sdram( uint64_t* dest, unsigned int blockNumber )
{
int startColumn = ( ( blockNumber & ( BLOCKS_PER_ROW - 1 ) ) * CHUNK_SIZE ) / RAM_BURST_COUNT;
int rowAndBank = blockNumber / BLOCKS_PER_ROW;
int row = rowAndBank & ( RAM_ROWS - 1 );
int bank = rowAndBank / RAM_ROWS;
int col = startColumn;
while( col < startColumn + CHUNK_SIZE/RAM_BURST_COUNT ) {
int x = mips_intr_disable();
sdram_wake();
sdram_bank(bank);
sdram_active(row);
int i;
for( i = 0; i < RAM_BURST_GROUP_COUNT; i++ ) {
*dest++ = sdram_read( col );
col += 1; //RAM_BURST_COUNT;
}
sdram_precharge();
sdram_precharge_all();
sdram_sleep();
mips_intr_restore (x);
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
}
}
static void
write_chunk_to_sdram( uint64_t* src, unsigned int blockNumber )
{
int startColumn = ( ( blockNumber & ( BLOCKS_PER_ROW - 1 ) ) * CHUNK_SIZE ) / RAM_BURST_COUNT;
int rowAndBank = blockNumber / BLOCKS_PER_ROW;
int row = rowAndBank & ( RAM_ROWS - 1 );
int bank = rowAndBank / RAM_ROWS;
int col = startColumn;
while( col < startColumn + CHUNK_SIZE/RAM_BURST_COUNT ) {
int x = mips_intr_disable();
sdram_wake();
sdram_bank(bank);
sdram_active(row);
int i;
for( i = 0; i < RAM_BURST_GROUP_COUNT; i++ ) {
sdram_write( col, *src++ );
col += 1; //RAM_BURST_COUNT;
}
sdram_precharge();
sdram_precharge_all();
sdram_sleep();
mips_intr_restore (x);
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
}
}
/*
* Read a block of data.
*/
static void
dev_read(unsigned blockno, char* data, unsigned nbytes)
{
blockno = blockno * (DEV_BSIZE/CHUNK_SIZE);
while( nbytes >= CHUNK_SIZE ) {
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
bcopy( swaptemp, data, CHUNK_SIZE );
data += CHUNK_SIZE;
blockno += 1;
nbytes -= CHUNK_SIZE;
}
if( nbytes ) {
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
bcopy( swaptemp, data, nbytes );
}
return;
}
/*
* Write a block of data.
*/
static void
dev_write (unsigned blockno, char *data, unsigned nbytes)
{
blockno = blockno * (DEV_BSIZE/CHUNK_SIZE);
while( nbytes >= CHUNK_SIZE ) {
bcopy( data, swaptemp, CHUNK_SIZE );
write_chunk_to_sdram( (uint64_t*) swaptemp, blockno );
data += CHUNK_SIZE;
blockno += 1;
nbytes -= CHUNK_SIZE;
}
if( nbytes ) {
read_chunk_from_sdram( (uint64_t*) swaptemp, blockno );
bcopy( data, swaptemp, nbytes );
write_chunk_to_sdram( (uint64_t*) swaptemp, blockno );
}
return;
}
int
swopen(dev_t dev, int flag, int mode)
{
static int has_been_opened = 0;
if (!has_been_opened) {
int x = mips_intr_disable();
sdram_init();
mips_intr_restore(x);
has_been_opened = 1;
#ifdef UCB_METER
/* Allocate statistics slot */
dk_alloc (&sw_dkn, 1, "sw");
#endif
}
return 0;
}
void
swstrategy(register struct buf *bp)
{
int s;
#if 0
printf ("sw0: %s block %u, length %u bytes, addr %p\n",
(bp->b_flags & B_READ) ? "read" : "write",
bp->b_blkno, bp->b_bcount, bp->b_addr);
#endif
led_control (LED_AUX, 1);
s = splbio();
#ifdef UCB_METER
if (sw_dkn >= 0) {
dk_busy |= 1 << sw_dkn;
dk_xfer[sw_dkn]++;
dk_bytes[sw_dkn] += bp->b_bcount;
}
#endif
unsigned adj = 0;
if (minor(bp->b_dev)==1) {
adj = SWAPSZ;
}
if (bp->b_flags & B_READ) {
dev_read (bp->b_blkno+adj, bp->b_addr, bp->b_bcount);
} else {
dev_write (bp->b_blkno+adj, bp->b_addr, bp->b_bcount);
}
#if 0
printf (" %02x", (unsigned char) bp->b_addr[0]);
int i;
for (i=1; i<bp->b_bcount; i++)
printf ("-%02x", (unsigned char) bp->b_addr[i]);
printf ("\n");
#endif
biodone (bp);
led_control (LED_AUX, 0);
splx (s);
#ifdef UCB_METER
if (sw_dkn >= 0)
dk_busy &= ~(1 << sw_dkn);
#endif
}
+4 -1
View File
@@ -48,7 +48,7 @@ DEFS += -DSD_PORT=SPI1CON -DSD_MHZ=10
DEFS += -DSD_CS0_PORT=TRISB -DSD_CS0_PIN=1
# LEDs at pins D0 (red), D1 (yellow), D2 (green)
DEFS += -DLED_TTY_PORT=TRISD -DLED_TTY_PIN=0
# Pin D0 is used for SD/MMC as signal SDO1
DEFS += -DLED_DISK_PORT=TRISD -DLED_DISK_PIN=1
DEFS += -DLED_KERNEL_PORT=TRISD -DLED_KERNEL_PIN=2
@@ -60,6 +60,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = yes
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
-158
View File
@@ -1,158 +0,0 @@
#
# Copyright (c) 1988 Regents of the University of California.
# All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that this notice is preserved and that due credit is given
# to the University of California at Berkeley. The name of the University
# may not be used to endorse or promote products derived from this
# software without specific prior written permission. This software
# is provided ``as is'' without express or implied warranty.
#
H = ../../include
M = ..
S = ../../kernel
vpath %.c $(M):$(S)
vpath %.S $(M):$(S)
# Kernel options.
DEFS += -I. -I$(H) -DKERNEL -DUCB_METER -DPIC32MX7
# CPU frequency 80 MHz.
DEFS += -DCPU_KHZ=80000
DEFS += -DBUS_KHZ=80000
#
# UBW32 board
# ===========
#
# Console on UART1
DEFS += -DCONSOLE_UART1
# SD/MMC card driver on SPI1
# /CS0 at pin A9 (and optional /CS1 at pin A10)
DEFS += -DSD_PORT=SPI1CON -DSD_MHZ=8
DEFS += -DSD_CS0_PORT=TRISA -DSD_CS0_PIN=9
DEFS += -DSD_CS1_PORT=TRISA -DSD_CS1_PIN=10
# LEDs at pins E0, E1, E2, E3
DEFS += -DLED_AUX_PORT=TRISE -DLED_AUX_PIN=0 -DLED_AUX_INVERT
DEFS += -DLED_DISK_PORT=TRISE -DLED_DISK_PIN=1 -DLED_DISK_INVERT
DEFS += -DLED_KERNEL_PORT=TRISE -DLED_KERNEL_PIN=2 -DLED_KERNEL_INVERT
DEFS += -DLED_TTY_PORT=TRISE -DLED_TTY_PIN=3 -DLED_TTY_INVERT
# Swap on sdram
DEFS += -DSWAPDEV=0x0100 -DSWAPSZ=2048
DEFS += -DKERNEL_EXECUTABLE_RAM
#DEFS += -DSW_DATA_PORT=TRISE -DSW_DATA_PIN=0
#DEFS += -DSW_RD_PORT=TRISE -DSW_RD_PIN=8
#DEFS += -DSW_WR_PORT=TRISE -DSW_WR_PIN=9
#DEFS += -DSW_LDA_PORT=TRISC -DSW_LDA_PIN=1
# Include or exclude drivers
# General Purpose I/O
DRIVER_GPIO = no
# Basic ADC interface
DRIVER_ADC = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
POWER_LED_PORT = TRISG
POWER_LED_PIN = 12
POWER_SWITCH_PORT = TRISG
POWER_SWITCH_PIN = 0
POWER_CONTROL_PORT = TRISE
POWER_CONTROL_PIN = 9
DEPFLAGS = -MT $@ -MD -MP -MF .deps/$*.dep
CFLAGS = -O $(DEFS) $(DEPFLAGS)
ASFLAGS = $(DEFS) $(DEPFLAGS)
include ../gcc-config.mk
CC = $(GCCPREFIX)gcc -EL -g -mips32r2
CC += -nostdinc -fno-builtin -Werror -Wall -fno-dwarf2-cfi-asm
LDFLAGS += -nostdlib -T using-bootloader.ld -Wl,-Map=unix.map
SIZE = $(GCCPREFIX)size
OBJDUMP = $(GCCPREFIX)objdump
OBJCOPY = $(GCCPREFIX)objcopy
# Machine-dependent files:
# startup.o MUST be loaded first.
KERNOBJ = startup.o clock.o devsw.o sysctl.o \
signal.o machdep.o mem.o exception.o
KERNOBJ += cons.o
# swap on sdram - this is incompatible with swap.o
KERNOBJ += sdram.o sdramp.o
# Kernel.
KERNOBJ += init_main.o init_sysent.o kern_clock.o \
kern_descrip.o kern_exec.o kern_exit.o kern_fork.o \
kern_mman.o kern_proc.o kern_prot.o \
kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o \
kern_subr.o kern_synch.o kern_sysctl.o kern_time.o \
subr_log.o subr_prf.o subr_rmap.o \
sys_generic.o sys_inode.o syscalls.o \
sys_pipe.o sys_process.o tty.o tty_conf.o \
tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o \
ufs_bmap.o ufs_dsort.o ufs_fio.o \
ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o \
ufs_syscalls.o ufs_syscalls2.o vfs_vnops.o \
vm_sched.o vm_swap.o vm_swp.o kern_glob.o
# Drivers.
KERNOBJ += sd.o
# Configuration-dependent files.
KERNOBJ += vers.o
# This makefile does the work including the right files and options for the drivers
include ../drivers.mk
all: .deps sys machine unix.elf
$(SIZE) unix.elf
clean:
rm -rf .deps *.o *.elf *.bin *.dis *.map *.srec core \
mklog assym.h vers.c genassym sys machine
.deps:
mkdir .deps
sys:
ln -s ../../include $@
machine:
ln -s .. $@
unix.elf: $(KERNOBJ) using-bootloader.ld
$(CC) $(LDFLAGS) $(KERNOBJ) -o $@
chmod -x $@
$(OBJDUMP) -d -S -z $@ > unix.dis
$(OBJCOPY) -O binary $@ unix.bin
$(OBJCOPY) -O ihex --change-addresses=0x80000000 $@ unix.hex
chmod -x $@ unix.bin
load: unix.elf
pic32prog -p unix.hex
vers.o: ../newvers.sh $(H)/*.h $(M)/*.[ch] $(S)/*.c
sh ../newvers.sh > vers.c
$(CC) -c vers.c
.SUFFIXES: .i .srec .hex .dis .cpp .cxx .bin .elf
.o.dis:
$(OBJDUMP) -d -z -S $< > $@
ifeq (.deps, $(wildcard .deps))
-include .deps/*.dep
endif
@@ -1,134 +0,0 @@
/*
* Linker script for PIC32 firmware using HID bootloader.
*/
OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
"elf32-littlemips")
OUTPUT_ARCH(mips)
ENTRY(_reset_vector_)
MEMORY
{
flash (rx) : ORIGIN = 0x9d005000, LENGTH = 492K
ram (rw!x): ORIGIN = 0x80000000, LENGTH = 24K
u0area (rw!x): ORIGIN = 0x80006000, LENGTH = 3K
uarea (rw!x): ORIGIN = 0x80006C00, LENGTH = 3K
keram (rwx) : ORIGIN = 0x80007800, LENGTH = 2K
/* Required by Microchip C32 linker */
kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x80000
kseg0_boot_mem : ORIGIN = 0x9FC00490, LENGTH = 0x970
exception_mem : ORIGIN = 0x9FC01000, LENGTH = 0x1000
kseg1_boot_mem : ORIGIN = 0xBFC00000, LENGTH = 0x490
kseg1_data_mem (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x20000
}
/* higher address of the user mode stack */
u0 = ORIGIN(u0area);
u = ORIGIN(uarea);
u_end = ORIGIN(uarea) + LENGTH(uarea);
_keram_start = ORIGIN(keram);
_keram_end = ORIGIN(keram) + LENGTH(keram);
SECTIONS
{
.text ORIGIN(flash) :
{
/* Exception handlers. */
*(.exception)
. = 0x1000;
/* Execution starts here. */
*(.startup)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.glue_7t) *(.glue_7)
__rodata_start = . ;
*(.rodata .rodata.* .gnu.linkonce.r.* .rel.dyn)
*(.dinit)
/* Align here to ensure that the .text section ends on word boundary. */
. = ALIGN (32 / 8);
_etext = .;
} > flash
/* Start data (internal SRAM). */
.data : AT (ADDR (.text) + SIZEOF (.text))
{
__data_start = . ;
_gp = .; /* We use only 32k RAM for kernel, so no need for 0x8000 offset. */
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(.data .data.* .gnu.linkonce.d.*)
*(.eh_frame)
_edata = .;
} > ram
.bss ADDR (.data) + SIZEOF (.data) (NOLOAD) :
{
__bss_start = .;
*(.dynbss)
*(.sbss)
*(.scommon)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN (32 / 8);
} > ram
__bss_end = . ;
_end = .;
/*
* RAM functions go at the end of our stack and heap allocation.
* Alignment of 2K required by the boundary register (BMXDKPBA).
*/
.ramfunc : AT (LOADADDR (.data) + SIZEOF (.data))
{
_ramfunc_begin = . ;
*(.ramfunc .ramfunc.*)
. = ALIGN(4) ;
_ramfunc_end = . ;
} >keram
_ramfunc_image_begin = LOADADDR(.ramfunc) ;
_ramfunc_length = SIZEOF(.ramfunc) ;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
}
+3
View File
@@ -61,6 +61,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = yes
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+3
View File
@@ -52,6 +52,9 @@ DRIVER_GPIO = yes
# Basic ADC interface
DRIVER_ADC = no
# Support userland program in flash
DRIVER_UFLASH = no
# Power control (power LED, and soft power-off by button)
# requires supported PSU (ATX)
DRIVER_POWER = no
+458
View File
@@ -0,0 +1,458 @@
/*
* uflash driver for PIC32.
*
* Based on GPIO driver:
* Copyright (C) 2012 Serge Vakulenko, <serge@vak.ru>
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is hereby
* granted, provided that the above copyright notice appear in all
* copies and that both that the copyright notice and this
* permission notice and warranty disclaimer appear in supporting
* documentation, and that the name of the author not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* The author disclaim all warranties with regard to this
* software, including all implied warranties of merchantability
* and fitness. In no event shall the author be liable for any
* special, indirect or consequential damages or any damages
* whatsoever resulting from loss of use, data or profits, whether
* in an action of contract, negligence or other tortious action,
* arising out of or in connection with the use or performance of
* this software.
*/
#include "param.h"
#include "conf.h"
#include "user.h"
#include "ioctl.h"
#include "uflash.h"
#include "systm.h"
#include "uio.h"
#include "stat.h"
#include "map.h"
#include "proc.h"
#include "buf.h"
#include "inode.h"
#include "namei.h"
#include "fs.h"
#include "mount.h"
#include "file.h"
#include "signalvar.h"
/* TODO: some sort of interlock is needed so that the contents
* of flash are not replaced while a processing that depends
* on the contents is executing.
*/
#define MINOR_UNIT 0x07 /* Minor mask: unit number */
#define FLASH_PAGE_SIZE 4096
#define FLASH_BUFFER_INT_COUNT 4
static void flashErasePage(unsigned addrPage);
static void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data);
// Flash operations
#define NVMOP_WORD_PGM 0x4001 // Word program operation
#define NVMOP_ROW_PGM 0x4003 // Row write
#define NVMOP_PAGE_ERASE 0x4004 // Page erase operation
#define USE_USER_FLASH_START (USER_FLASH_START-0x20000000UL)
/*
* To enable debug output, comment out the first line,
* and uncomment the second line.
*/
#define PRINTDBG(...) /*empty*/
//#define PRINTDBG printf
char targetToFlash[31] = "";
int
uflash_open (dev, flag, mode)
dev_t dev;
{
if (u.u_uid != 0)
return EPERM;
return 0;
}
int
uflash_close (dev, flag, mode)
dev_t dev;
{
return 0;
}
int
uflash_read (dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
register struct iovec *iov;
register u_int cnt;
char *buf = targetToFlash;
cnt = strlen(targetToFlash);
/* I/o size should be large enough. */
iov = uio->uio_iov;
if (iov->iov_len < cnt)
return EIO;
/* Read only cnt bytes. */
if (uio->uio_offset >= cnt)
return 0;
cnt -= uio->uio_offset;
/* Print port status to buffer. */
//PRINTDBG ("uflash_read -> %s", buf);
bcopy (buf + uio->uio_offset, iov->iov_base, cnt);
iov->iov_base += cnt;
iov->iov_len -= cnt;
uio->uio_resid -= cnt;
uio->uio_offset += cnt;
return 0;
}
int
uflash_write (dev, uio, flag)
dev_t dev;
struct uio *uio;
int flag;
{
register struct iovec *iov = uio->uio_iov;
register u_int cnt = 30;
char * buf = targetToFlash;
/* I/o size should be large enough. */
if (iov->iov_len > cnt)
return EIO;
if( iov->iov_len < cnt ) cnt = iov->iov_len;
cnt -= uio->uio_offset;
bcopy (iov->iov_base, buf+uio->uio_offset, cnt);
buf[uio->uio_offset+cnt]=0;
iov->iov_base += cnt;
iov->iov_len -= cnt;
uio->uio_resid -= cnt;
uio->uio_offset += cnt;
//PRINTDBG ("uflash_read ('%s')\n", buf);
return 0;
}
/*
* Commands:
* UFLASH_LOAD - load the program specified into user flash
*/
int
uflash_ioctl (dev, cmd, addr, flag)
dev_t dev;
register u_int cmd;
caddr_t addr;
{
int result = 0;
struct inode *ip;
//unsigned unit = cmd & 0xff;
cmd &= ~0xff;
if( cmd != UFLASH_LOAD )
return EINVAL;
struct nameidata nd;
register struct nameidata *ndp = &nd;
//printf ("uflash_ioctl ('%s', ['%s', '%s', ...])\n", uap->fname, uap->argp[0], uap->argp[1]);
NDINIT (ndp, LOOKUP, FOLLOW, targetToFlash);
ip = namei (ndp);
if (ip == NULL) {
result = EACCES;
goto done;
}
struct stat sb;
int err = ino_stat (ip, &sb);
if( err ) {
result = err;
goto done;
}
/* Erase Pages */
unsigned address = USE_USER_FLASH_START;
int remaining = (int)sb.st_size;
while( remaining > 0 ) {
flashErasePage( address );
address += 4096;
remaining -= 4096;
}
/* TODO: reorgainize writing so that everything except the first
* couple of bytes is written to flash and verified before
* writing and verifying the first couple of bytes. The purpose
* would be to leave the uflash area in an invalid state so that
* the stub code would not attempt to execute it.
*/
/* Write bin */
address = USE_USER_FLASH_START;
remaining = (int)sb.st_size;
unsigned buffer[FLASH_BUFFER_INT_COUNT];
while( remaining ) {
unsigned readsize = FLASH_BUFFER_INT_COUNT * sizeof(unsigned);
if( readsize > remaining ) readsize = remaining;
int resid;
err = rdwri (UIO_READ, ip, (caddr_t)buffer, readsize, (off_t) address - USE_USER_FLASH_START, IO_UNIT, &resid);
if( err ) {
result = err;
goto done;
}
if( resid ) {
result = EIO;
goto done;
}
flashWriteUint32(address, buffer, FLASH_BUFFER_INT_COUNT);
address += readsize;
remaining -= readsize;
}
/* Verify bin */
address = USE_USER_FLASH_START;
remaining = (int)sb.st_size;
while( remaining ) {
unsigned readsize = FLASH_BUFFER_INT_COUNT * sizeof(unsigned);
if( readsize > remaining ) readsize = remaining;
int resid;
err = rdwri (UIO_READ, ip, (caddr_t)buffer, readsize, (off_t) address - (unsigned)USE_USER_FLASH_START, IO_UNIT, &resid);
if( err ) {
result = err;
goto done;
}
if( resid ) {
result = EIO;
goto done;
}
int i;
for( i = 0; i < readsize; ++i ) {
if( ((char*)address)[i] != ((char*)buffer)[i] ) {
result = EIO;
goto done;
}
}
address += readsize;
remaining -= readsize;
}
done:
if (ip)
iput(ip);
return result;
}
/*** void flashOperation(unsigned nvmop, unsigned addr, unsigned data)
**
** Synopsis:
** Performs either a page erase, word write, or row write
**
** Parameters:
** nvmop either NVMOP_PAGE_ERASE, NVMOP_WORD_PGM, or NVMOP_ROW_PGM
** addr the unsigned_t flash address of: the page to erase, word location to write, or row location to write
** data a unsigned_t of data to write, or the unsigned_t of the SRAM address containing the array of data to write to the row
**
** Return Values:
** True if successful, false if failed
**
** Errors:
** None
**
** Notes:
** data has no meaning when page erase is specified and should be set to 0ul
**
*/
/*
* nvm_operation is borrowed from usb_boot.c and is controlled
* by the following copyright:
*
* USB HID bootloader for PIC32 microcontroller.
*
* Based on Microchip sources.
* Heavily rewritten by Serge Vakulenko, <serge@vak.ru>.
*
* The software supplied herewith by Microchip Technology Incorporated
* (the 'Company') for its PIC(R) Microcontroller is intended and
* supplied to you, the Company's customer, for use solely and
* exclusively on Microchip PIC Microcontroller products. The
* software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this license.
*
* THIS SOFTWARE IS PROVIDED IN AN 'AS IS' CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
static void nvm_operation (unsigned op, unsigned address, unsigned data)
{
int x;
// Convert virtual address to physical
NVMADDR = address & 0x1fffffff;
NVMDATA = data;
// Disable interrupts
x = mips_intr_disable();
// Enable Flash Write/Erase Operations
NVMCON = PIC32_NVMCON_WREN | op;
// Data sheet prescribes 6us delay for LVD to become stable.
// To be on the safer side, we shall set 7us delay.
udelay (7);
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA;
NVMCONSET = PIC32_NVMCON_WR;
// Wait for WR bit to clear
while (NVMCON & PIC32_NVMCON_WR)
continue;
// Disable Flash Write/Erase operations
NVMCONCLR = PIC32_NVMCON_WREN;
// Enable interrupts
mips_intr_restore (x);
#if 0
// Check error status
if (NVMCON & (PIC32_NVMCON_WRERR | PIC32_NVMCON_LVDERR)) {
TODO;
}
#endif
}
// flashErasePage and flashWriteUint32 where originally from the file flash.c
// implements the low level flash control and access.
//
// flash.c originated from the cpustick.com skeleton project from
// http://www.cpustick.com/downloads.htm and was originally written
// by Rich Testardi; please preserve this reference and share bug
// fixes with rich@testardi.com.
/*** void flashErasePage(unsigned addrPage)
**
** Synopsis:
** Erases the page starting at the page address.
*
** Parameters:
** addrPage The virtual address of the page to erase
**
** Return Values:
** None
**
** Errors:
** None
**
** Notes:
**
** addrPage must be page aligned.
**
*/
static void flashErasePage(unsigned addrPage)
{
int i;
int j;
unsigned x = ~0;
unsigned *rgUint32 = (unsigned *) addrPage;
// we learned that just because the flash does not successfully
// erase on the first attempt, it might on another. We found that
// we can double the life of flash by attempting to
// erase the flash up to 5 times before quitting.
for(j=0; j<5; j++) {
// first check to see if the page needs to be erased
for (i = 0; i < FLASH_PAGE_SIZE/sizeof(unsigned); i++) {
x &= rgUint32[i];
}
// flash erased, we are done.
if(x == ~0) {
break;
}
// Unlock and Erase Page
nvm_operation(NVMOP_PAGE_ERASE, addrPage, 0);
}
// at this point, we don't care if the flash ever actually erased as
// as we will catch the failure when we verify the programming.
}
/*** void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data)
**
** Synopsis:
** Writes an array to unsigned to flash
*
** Parameters:
** rgu32Data Pointer to an array of unsigned
** cu32Data The number of unsigned to write
**
** Return Values:
** None
**
** Errors:
** None
**
** Notes:
**
** Assumes the pages have already been erased.
**
*/
static void flashWriteUint32(unsigned addrUint32, unsigned *rgu32Data, unsigned cu32Data)
{
int i = 0;
for(i=0; i < cu32Data; i++) {
// only do this if the data is not what is already in flash
if(rgu32Data[i] != ~0) {
// Write the data
nvm_operation(NVMOP_WORD_PGM, addrUint32, rgu32Data[i]);
}
addrUint32 += sizeof(unsigned);
}
}
+1 -1
View File
@@ -563,7 +563,7 @@ int main()
CHECONSET = 0x30;
/* Disable JTAG port, to use it for i/o. */
DDPCON = 0;
/*DDPCON = 0;*/
/* Config register: enable kseg0 caching. */
mips_write_c0_register (C0_CONFIG, 0,
+2
View File
@@ -45,8 +45,10 @@ void cninit()
IECSET(1) = 1 << (PIC32_IRQ_USB - 32);
/* Wait for any user input. */
led_control (LED_KERNEL, 1);
while (! cdc_consume(0))
usb_device_tasks();
led_control (LED_KERNEL, 0);
}
void cnidentify()
+2 -2
View File
@@ -42,10 +42,10 @@ I = ..
#CFLAGS += -DDIP -DFLASH_JUMP=0x9d000000
# Microchip USB/Ethernet Starter Kit
#CFLAGS += -DSTARTERKIT -DFLASH_JUMP=0x9d000000
CFLAGS += -DSTARTERKIT -DFLASH_JUMP=0x9d000000
# Fubarino
CFLAGS += -DFUBARINO -DFLASH_JUMP=0x9d000000
#CFLAGS += -DFUBARINO -DFLASH_JUMP=0x9d000000
all: usbboot.hex usbboot.elf
$(SIZE) usbboot.elf