mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
dma: add a new driver to support r61524
Also add a power interface (without driving code) and switch toolchain because the previous sh4eb-nofpu-elf toolchain was not completely FPU-free.
This commit is contained in:
parent
f33cb3cf80
commit
04231ea5d6
18 changed files with 578 additions and 144 deletions
|
@ -47,8 +47,8 @@ or both. There are a few dependencies:
|
|||
* A suitable GCC toolcahin in the `PATH`. You can absolutely *not* build gint
|
||||
with your system compiler!
|
||||
* For fx-9860G II, `sh3eb-elf` is strongly advised
|
||||
* For fx-CG 50, `sh4eb-nofpu-elf` is slightly better but `sh3eb-elf` is
|
||||
completely fine
|
||||
* For fx-CG 50, `sh4eb-elf` (with `-m4-nofpu`) is slightly better but
|
||||
`sh3eb-elf` is completely fine
|
||||
* The [fxSDK](http://git.planet-casio.com/lephe/fxsdk) installed and available
|
||||
in the PATH. You will need `fxsdk` and `fxconv` to build gint, and if you
|
||||
intend to develop add-ins for fx-9860G II, you probably want `fxg1a` as well.
|
||||
|
@ -83,7 +83,7 @@ with `--prefix`, or if you built your compiler as root.
|
|||
### Building for fx-CG 50
|
||||
|
||||
Create a build directory and configure in it. The default toolchain is
|
||||
`sh4eb-nofpu-elf`, if you wish to build with `sh3eb-elf`, you need to add a
|
||||
`sh4eb-elf`, if you wish to build with `sh3eb-elf`, you need to add a
|
||||
command-line option `--toolchain=sh3eb-elf`.
|
||||
|
||||
% mkdir build.cg && cd build.cg
|
||||
|
|
6
configure
vendored
6
configure
vendored
|
@ -45,7 +45,7 @@ Target selection:
|
|||
|
||||
fxcg50 covers just the fx-CG 50; there is some unofficial compatibility with
|
||||
fx-CG 10/20. All of these are SH4-only.
|
||||
Default toolchain is 'sh4eb-nofpu-elf'.
|
||||
Default toolchain is 'sh4eb-elf'.
|
||||
|
||||
Build options:
|
||||
--toolchain=TRIPLET Build with a different toolchain
|
||||
|
@ -102,11 +102,13 @@ for arg; do case "$arg" in
|
|||
toolchain=${toolchain:-sh3eb-elf};;
|
||||
"fxcg50")
|
||||
target=fxcg50
|
||||
toolchain=${toolchain:-sh4eb-nofpu-elf};;
|
||||
toolchain=${toolchain:-sh4eb-elf};;
|
||||
*)
|
||||
echo "error: invalid target '$target'"
|
||||
fail=true
|
||||
esac;;
|
||||
--toolchain=*)
|
||||
toolchain=${arg#*=};;
|
||||
|
||||
--prefix=*)
|
||||
prefix=${arg#*=};;
|
||||
|
|
69
include/gint/dma.h
Normal file
69
include/gint/dma.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//---
|
||||
// gint:dma - Direct Memory Access for efficient data transfer
|
||||
//
|
||||
// Currently this module is used only to transfer data to the display on
|
||||
// fxcg50, but fast memcpy() is apparently possible as well.
|
||||
//---
|
||||
|
||||
#ifndef GINT_DMA
|
||||
#define GINT_DMA
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
|
||||
/* dma_size_t - Transfer block size */
|
||||
typedef enum
|
||||
{
|
||||
/* Normal transfers of 1, 2, 4, 8, 16 or 32 bytes at a time */
|
||||
DMA_1B = 0,
|
||||
DMA_2B = 1,
|
||||
DMA_4B = 2,
|
||||
DMA_8B = 7,
|
||||
DMA_16B = 3,
|
||||
DMA_32B = 4,
|
||||
|
||||
/* Transfers of 16 or 32 bytes divided in two operations */
|
||||
DMA_16B_DIV = 11,
|
||||
DMA_32B_DIV = 12,
|
||||
|
||||
} dma_size_t;
|
||||
|
||||
/* dma_address_t - Addressing mode for source and destination regions */
|
||||
typedef enum
|
||||
{
|
||||
/* Fixed address mode: the same address is read/written at each step */
|
||||
DMA_FIXED = 0,
|
||||
/* Increment: address is incremented by transfer size at each step */
|
||||
DMA_INC = 1,
|
||||
/* Decrement: only allowed for 1/2/4-byte transfers */
|
||||
DMA_DEC = 2,
|
||||
/* Fixed division mode: address is fixed even in 16/32-divide mode */
|
||||
DMA_FIXEDDIV = 3,
|
||||
|
||||
} dma_address_t;
|
||||
|
||||
/* dma_transfer() - Start a data transfer on channel 0
|
||||
|
||||
This function returns just when the transfer starts. The transfer will end
|
||||
later on and the DMA will be stopped by an interrupt. Call
|
||||
dma_transfer_wait() if you need to wait for the transfer to finish. Don't
|
||||
start a new transfer until the current one is finished!
|
||||
|
||||
@size Transfer size
|
||||
@blocks Number of blocks (transferred memory = size * blocks)
|
||||
@src Source pointer, must be aligned with transfer size
|
||||
@src_mode Source address mode
|
||||
@dst Destination address, must be aligned with transfer size
|
||||
@dst_mode Destination address mode */
|
||||
void dma_transfer(dma_size_t size, uint length,
|
||||
void *src, dma_address_t src_mode,
|
||||
void *dst, dma_address_t dst_mode);
|
||||
|
||||
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish
|
||||
|
||||
You should call this function when you need to transfer to be complete
|
||||
before continuing execution. If you are sure that the transfer is finished,
|
||||
this is not necessary (the only way to know is to look at the DMA registers
|
||||
or record interrupts). */
|
||||
void dma_transfer_wait(void);
|
||||
|
||||
#endif /* GINT_DMA */
|
|
@ -1,9 +1,9 @@
|
|||
//---
|
||||
// gint:core:cpg - Clock Pulse Generator
|
||||
// gint:mpu:cpg - Clock Pulse Generator
|
||||
//---
|
||||
|
||||
#ifndef GINT_CORE_CPG
|
||||
#define GINT_CORE_CPG
|
||||
#ifndef GINT_MPU_CPG
|
||||
#define GINT_MPU_CPG
|
||||
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/defs/types.h>
|
||||
|
@ -79,4 +79,4 @@ typedef volatile struct
|
|||
|
||||
#define SH7305_CPG (*((sh7305_cpg_t *)0xa4150000))
|
||||
|
||||
#endif /* GINT_CORE_CPG */
|
||||
#endif /* GINT_MPU_CPG */
|
||||
|
|
89
include/gint/mpu/dma.h
Normal file
89
include/gint/mpu/dma.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
//---
|
||||
// gint:mpu:dma - Direct Memory Access control
|
||||
//
|
||||
// The DMA is a major module on fxcg50 because it is needed to send data
|
||||
// to the display at a reasonable speed. On fx9860g, it is very rarely
|
||||
// used, if ever.
|
||||
//---
|
||||
|
||||
#ifndef GINT_MPU_DMA
|
||||
#define GINT_MPU_DMA
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
|
||||
//---
|
||||
// SH7305 Direct Memory Access Controller. Refer to:
|
||||
// "Renesas SH7724 User's Manual: Hardware"
|
||||
// Section 16: "Direct Memory Access Controller (DMAC)"
|
||||
//---
|
||||
|
||||
/* sh7305_dma_channel_t - One of the main 6 channels of the DMA
|
||||
Note that the many settings are only available on channels 0 to 3 (denoted
|
||||
by [0..3]) or on channels 0 and 1 (denoted by [0,1]).
|
||||
The documentation is apparently wrong about the placement is TS[3:2], the
|
||||
neighbouring read-only bit must be swapped before TS[3:2]. */
|
||||
typedef volatile struct
|
||||
{
|
||||
uint32_t SAR;
|
||||
uint32_t DAR;
|
||||
|
||||
/* Mind that the 8 upper bits should always be written as 0 */
|
||||
uint32_t TCR;
|
||||
|
||||
lword_union(CHCR,
|
||||
uint32_t :1;
|
||||
uint32_t LCKN :1; /* Bus Right Release Enable */
|
||||
uint32_t :2;
|
||||
uint32_t RPT :3; /* Repeat setting [0..3] */
|
||||
uint32_t DA :1; /* DREQ Asynchronous [0,1] */
|
||||
|
||||
uint32_t DO :1; /* DMA Overrun [0,1] */
|
||||
uint32_t :1;
|
||||
uint32_t TS_32 :2; /* Transfer Size (upper half) */
|
||||
uint32_t HE :1; /* Half-End flag [0..3] */
|
||||
uint32_t HIE :1; /* Half-end Interrupt Enable [0..3] */
|
||||
uint32_t AM :1; /* Acknowledge mode [0,1] */
|
||||
uint32_t AL :1; /* Acknowledge level [0,1] */
|
||||
|
||||
uint32_t DM :2; /* Destination address Mode */
|
||||
uint32_t SM :2; /* Source address Mode */
|
||||
uint32_t RS :4; /* Resource Select [0,1] */
|
||||
|
||||
uint32_t DL :1; /* DREQ Level [0,1] */
|
||||
uint32_t DS :1; /* DREQ Source select[0,1] */
|
||||
uint32_t TB :1; /* Transfer Bus Mode */
|
||||
uint32_t TS_10 :2; /* Transfer Size (lower half) */
|
||||
uint32_t IE :1; /* Interrupt Enable */
|
||||
uint32_t TE :1; /* Transfer End flag */
|
||||
uint32_t DE :1; /* DMA Enable */
|
||||
);
|
||||
|
||||
} GPACKED(4) sh7305_dma_channel_t;
|
||||
|
||||
/* sh7305_dma_t - DMA Controller */
|
||||
typedef volatile struct
|
||||
{
|
||||
sh7305_dma_channel_t DMA0;
|
||||
sh7305_dma_channel_t DMA1;
|
||||
sh7305_dma_channel_t DMA2;
|
||||
sh7305_dma_channel_t DMA3;
|
||||
|
||||
word_union(OR,
|
||||
uint16_t CMS :4; /* Cycle steal Mode Select */
|
||||
uint16_t :2;
|
||||
uint16_t PR :2; /* PRiority mode */
|
||||
uint16_t :5;
|
||||
uint16_t AE :1; /* Address Error flag */
|
||||
uint16_t NMIF :1; /* NMI Flag */
|
||||
uint16_t DME :1; /* DMA Master Enable */
|
||||
);
|
||||
pad(14);
|
||||
|
||||
sh7305_dma_channel_t DMA4;
|
||||
sh7305_dma_channel_t DMA5;
|
||||
|
||||
} GPACKED(4) sh7305_dma_t;
|
||||
|
||||
#define SH7305_DMA (*((sh7305_dma_t *)0xfe008020))
|
||||
|
||||
#endif /* GINT_MPU_DMA */
|
|
@ -1,5 +1,5 @@
|
|||
//---
|
||||
// gint:core:intc - Interrupt Controller
|
||||
// gint:mpu:intc - Interrupt Controller
|
||||
//
|
||||
// The interrupt controller is unwieldy because SH7705 and SH7305 have a
|
||||
// completely different interface. Everything here is split up and you'll
|
||||
|
@ -9,8 +9,8 @@
|
|||
// management. This is probably what you are looking for.
|
||||
//---
|
||||
|
||||
#ifndef GINT_CORE_INTC
|
||||
#define GINT_CORE_INTC
|
||||
#ifndef GINT_MPU_INTC
|
||||
#define GINT_MPU_INTC
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
|
||||
|
@ -296,4 +296,4 @@ typedef struct
|
|||
extern sh7705_intc_t SH7705_INTC;
|
||||
extern sh7305_intc_t SH7305_INTC;
|
||||
|
||||
#endif /* GINT_CORE_INTC */
|
||||
#endif /* GINT_MPU_INTC */
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//---
|
||||
// gint:core:pfc - Pin Function Controller
|
||||
// gint:mpu:pfc - Pin Function Controller
|
||||
//
|
||||
// The Pin Function Controller has a simple register interface, the main
|
||||
// difficulty is still understanding the role of its pins.
|
||||
//---
|
||||
|
||||
#ifndef GINT_CORE_PFC
|
||||
#define GINT_CORE_PFC
|
||||
#ifndef GINT_MPU_PFC
|
||||
#define GINT_MPU_PFC
|
||||
|
||||
#include <gint/defs/attributes.h>
|
||||
#include <gint/defs/types.h>
|
||||
|
@ -75,4 +75,4 @@ typedef volatile struct
|
|||
// TODO: Document the SH7305 Pin Function Controller
|
||||
//---
|
||||
|
||||
#endif /* GINT_CORE_PFC */
|
||||
#endif /* GINT_MPU_PFC */
|
||||
|
|
102
include/gint/mpu/power.h
Normal file
102
include/gint/mpu/power.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
//---
|
||||
// gint:mpu:power- Standby modes and power management
|
||||
//---
|
||||
|
||||
#ifndef GINT_MPU_POWER
|
||||
#define GINT_MPU_POWER
|
||||
|
||||
#include <gint/defs/types.h>
|
||||
|
||||
//---
|
||||
// SH7305 Standby modes and power management Refer to:
|
||||
// "Renesas SH7724 User's Manual: Hardware"
|
||||
// Section 18: "Reset and Power-Down Modes"
|
||||
//---
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
/* Standby Control Register: only one of the bits may be set at any
|
||||
given time. Setting several bits is prohibited! */
|
||||
lword_union(STBCR,
|
||||
uint32_t :24;
|
||||
uint32_t STBY :1; /* Map [sleep] to standby mode */
|
||||
uint32_t :1;
|
||||
uint32_t RSTBY :1; /* Map [sleep] to R-standby mode */
|
||||
uint32_t USTBY :1; /* Map [sleep] to U-standby mode */
|
||||
uint32_t :4;
|
||||
);
|
||||
pad(12);
|
||||
|
||||
/* Module Stop Control Register 0
|
||||
Stopping the TLB (bit 31), IC (bit 30 or OC (bit 29) seems somewhat
|
||||
dangerous, plus requires special operations. */
|
||||
lword_union(MSTPCR0,
|
||||
uint32_t TLB :1;
|
||||
uint32_t IC :1;
|
||||
uint32_t OC :1;
|
||||
uint32_t RS :1;
|
||||
uint32_t IL :1;
|
||||
uint32_t SndCache :1;
|
||||
uint32_t :1;
|
||||
uint32_t FPU :1;
|
||||
|
||||
uint32_t :1;
|
||||
uint32_t INTC :1;
|
||||
uint32_t DMAC0 :1;
|
||||
uint32_t SuperHyway :1;
|
||||
uint32_t HUDI :1;
|
||||
uint32_t DBG :1;
|
||||
uint32_t UDB :1;
|
||||
uint32_t Debug :1;
|
||||
|
||||
uint32_t TMU0 :1;
|
||||
uint32_t CMT :1;
|
||||
uint32_t RWDT :1;
|
||||
uint32_t DMAC1 :1;
|
||||
uint32_t :1;
|
||||
uint32_t TMU1 :1;
|
||||
uint32_t SCIF0 :1;
|
||||
uint32_t SCIF1 :1;
|
||||
|
||||
uint32_t SCIF2 :1;
|
||||
uint32_t SCIF3 :1;
|
||||
uint32_t SCIF4 :1;
|
||||
uint32_t SCIF5 :1;
|
||||
uint32_t :1;
|
||||
uint32_t MSIOF0 :1;
|
||||
uint32_t MSIOF1 :1;
|
||||
uint32_t :1;
|
||||
);
|
||||
|
||||
/* Module Stop Control Register 1 */
|
||||
lword_union(MSTPCR1,
|
||||
uint32_t :19;
|
||||
uint32_t KEYSC :1;
|
||||
uint32_t RTC :1;
|
||||
uint32_t :1;
|
||||
uint32_t I2C0 :1;
|
||||
uint32_t I2C1 :1;
|
||||
uint32_t :8;
|
||||
);
|
||||
|
||||
/* Module Stop Control Register 2
|
||||
I stripped down this one to remove any fancy modules from the SH7724
|
||||
that are unlikely to even be present in the SH7305. */
|
||||
lword_union(MSTPCR2,
|
||||
uint32_t :6;
|
||||
uint32_t TPU :1;
|
||||
uint32_t :4;
|
||||
uint32_t USB0 :1;
|
||||
uint32_t :20;
|
||||
);
|
||||
pad(4);
|
||||
|
||||
/* Boot Address Register
|
||||
I really don't suggest writing to BAR. */
|
||||
uint32_t const BAR;
|
||||
|
||||
} sh7305_power_t;
|
||||
|
||||
#define SH7305_POWER (*((sh7305_power_t *)0xa4150020))
|
||||
|
||||
#endif /* GINT_MPU_POWER */
|
|
@ -1,9 +1,9 @@
|
|||
//---
|
||||
// gint:mod:rtc - Real-Time Clock
|
||||
// gint:mpu:rtc - Real-Time Clock
|
||||
//---
|
||||
|
||||
#ifndef GINT_CORE_RTC
|
||||
#define GINT_CORE_RTC
|
||||
#ifndef GINT_MPU_RTC
|
||||
#define GINT_MPU_RTC
|
||||
|
||||
#include <gint/defs/attributes.h>
|
||||
|
||||
|
@ -75,4 +75,4 @@ typedef volatile struct
|
|||
#define SH7705_RTC (*((rtc_t *)0xfffffec0))
|
||||
#define SH7305_RTC (*((rtc_t *)0xa413fec0))
|
||||
|
||||
#endif /* GINT_CORE_RTC */
|
||||
#endif /* GINT_MPU_RTC */
|
||||
|
|
|
@ -20,8 +20,8 @@ include $(CONFIG)
|
|||
ifeq "$(CONFIG.TOOLCHAIN)" "sh3eb-elf"
|
||||
machine := -m3 -mb
|
||||
endif
|
||||
ifeq "$(CONFIG.TOOLCHAIN)" "sh4eb-nofpu-elf"
|
||||
machine := -m4 -mb
|
||||
ifeq "$(CONFIG.TOOLCHAIN)" "sh4eb-elf"
|
||||
machine := -m4-nofpu -mb
|
||||
endif
|
||||
|
||||
# Compiler flags, assembler flags, dependency generation, archiving
|
||||
|
|
|
@ -97,8 +97,12 @@ void bootlog_mapped(int rom, int ram)
|
|||
|
||||
print(20, 3, "%c%c", (rom >= (int)rom_size) ? 'F' : 'f',
|
||||
isSH3() ? 'u' : 'U');
|
||||
print(9, 2, (ram > 8192) ? "E" : "e");
|
||||
print(19, 1, "M");
|
||||
|
||||
#ifdef FX9860G
|
||||
print(9, 2, (ram > 8192) ? "E" : "e");
|
||||
#endif
|
||||
|
||||
dupdate();
|
||||
}
|
||||
|
||||
|
@ -132,7 +136,7 @@ void bootlog_driver(const char *drv, const char *status)
|
|||
print(x, y, "%3s", drv);
|
||||
x += 4;
|
||||
|
||||
if(x + y >= 22) y++;
|
||||
if(x + y >= 22) x=1, y++;
|
||||
|
||||
/* Positioning for the driver message */
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
** gint:core:exch - Exception handlers
|
||||
*/
|
||||
|
||||
.global _exch_entry_7305
|
||||
.global _exch_entry_7305
|
||||
|
||||
#ifdef FX9860G
|
||||
.global _exch_entry_7705
|
||||
.global _exch_entry_7705
|
||||
#endif
|
||||
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* SH7305-TYPE DEBUG EXCEPTION HANDLER - 26 BYTES */
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
** blocks depending on its configuration.
|
||||
*/
|
||||
|
||||
.global _inth_entry_7305
|
||||
.global _inth_entry_7305
|
||||
|
||||
#ifdef FX9860G
|
||||
.global _inth_entry_7705
|
||||
.global _inth_entry_7705
|
||||
#endif
|
||||
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* Interrupt handlers
|
||||
|
||||
|
@ -100,8 +100,8 @@ _inth_entry_7705:
|
|||
1: .long 0xa4000000 /* INTEVT2 register */
|
||||
2: .long _inth_remap
|
||||
|
||||
.section .gint.data
|
||||
.align 4
|
||||
.section .gint.data
|
||||
.align 4
|
||||
|
||||
/* EVENT CODE TRANSLATION TABLE - 96 BYTES */
|
||||
|
||||
|
|
140
src/dma/dma.c
Normal file
140
src/dma/dma.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
#include <gint/mpu.h>
|
||||
#include <gint/mpu/dma.h>
|
||||
#include <gint/mpu/power.h>
|
||||
#include <gint/mpu/intc.h>
|
||||
#include <gint/dma.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/clock.h>
|
||||
|
||||
#define DMA SH7305_DMA
|
||||
#define INTC SH7305_INTC
|
||||
#define POWER SH7305_POWER
|
||||
|
||||
//---
|
||||
// Driver interface
|
||||
//---
|
||||
|
||||
/* dma_transfer() - Perform a data transfer */
|
||||
void dma_transfer(dma_size_t size, uint blocks,
|
||||
void *src, dma_address_t src_mode,
|
||||
void *dst, dma_address_t dst_mode)
|
||||
{
|
||||
/* Safety guard: only start a transfer if there's not one running */
|
||||
if(DMA.DMA0.CHCR.DE) return;
|
||||
|
||||
/* Disable DMA0 and disable the master DMA switch */
|
||||
DMA.DMA0.CHCR.DE = 0;
|
||||
DMA.OR.DME = 0;
|
||||
|
||||
/* Set DMA source and target address */
|
||||
DMA.DMA0.SAR = (uint32_t)src & 0x1fffffff;
|
||||
DMA.DMA0.DAR = (uint32_t)dst & 0x1fffffff;
|
||||
|
||||
/* Set the number of blocks to be transferred */
|
||||
DMA.DMA0.TCR = blocks;
|
||||
|
||||
/* Fill in CHCR. Set RS=0100 (auto-request) and the user-provided
|
||||
values for TS (transfer size), DM and SM (address modes) */
|
||||
DMA.DMA0.CHCR.lword = 0x00000400;
|
||||
DMA.DMA0.CHCR.TS_32 = (size >> 2);
|
||||
DMA.DMA0.CHCR.TS_10 = (size & 3);
|
||||
DMA.DMA0.CHCR.DM = dst_mode;
|
||||
DMA.DMA0.CHCR.SM = src_mode;
|
||||
DMA.DMA0.CHCR.IE = 1;
|
||||
|
||||
/* Prepare DMAOR by enabling the master switch and clearing the
|
||||
blocking flags. */
|
||||
DMA.OR.DME = 1;
|
||||
DMA.OR.AE = 0;
|
||||
DMA.OR.NMIF = 0;
|
||||
|
||||
/* Enable channel 0, starting the DMA transfer. */
|
||||
DMA.DMA0.CHCR.DE = 1;
|
||||
}
|
||||
|
||||
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish */
|
||||
void dma_transfer_wait(void)
|
||||
{
|
||||
/* The master switch is cut when the transfer ends */
|
||||
while(DMA.OR.DME) sleep();
|
||||
}
|
||||
|
||||
//---
|
||||
// Initialization
|
||||
//---
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
/* This driver is not implemented on SH3 */
|
||||
if(isSH3()) return;
|
||||
|
||||
/* Install the interrupt handler from dma/inth.s */
|
||||
extern void inth_dma_dma0(void);
|
||||
gint_inthandler(0x800, inth_dma_dma0, 32);
|
||||
|
||||
/* Set interrupt priority to 3 */
|
||||
gint_intlevel(16, 3);
|
||||
|
||||
/* Unmask the DMA0 interrupt */
|
||||
INTC.MSKCLR->IMR1 = 0x01;
|
||||
}
|
||||
|
||||
//---
|
||||
// Context system for this driver
|
||||
//---
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t SAR0, DAR0, TCR0, CHCR0;
|
||||
uint16_t OR;
|
||||
int clock;
|
||||
|
||||
} GPACKED(4) ctx_t;
|
||||
|
||||
/* One buffer for the system state will go in gint's .bss section */
|
||||
GBSS static ctx_t sys_ctx;
|
||||
|
||||
static void ctx_save(void *buf)
|
||||
{
|
||||
ctx_t *ctx = buf;
|
||||
|
||||
ctx->SAR0 = DMA.DMA0.SAR;
|
||||
ctx->DAR0 = DMA.DMA0.DAR;
|
||||
ctx->TCR0 = DMA.DMA0.TCR;
|
||||
ctx->CHCR0 = DMA.DMA0.CHCR.lword;
|
||||
|
||||
ctx->OR = DMA.OR.word;
|
||||
|
||||
/* Save the supply status of the DMA0 clock */
|
||||
ctx->clock = POWER.MSTPCR0.DMAC0;
|
||||
}
|
||||
|
||||
static void ctx_restore(void *buf)
|
||||
{
|
||||
ctx_t *ctx = buf;
|
||||
|
||||
DMA.DMA0.SAR = ctx->SAR0;
|
||||
DMA.DMA0.DAR = ctx->DAR0;
|
||||
DMA.DMA0.TCR = ctx->TCR0;
|
||||
DMA.DMA0.CHCR.lword = ctx->CHCR0;
|
||||
|
||||
DMA.OR.word = ctx->OR;
|
||||
|
||||
/* Restore the supply status of the DMA0 clock */
|
||||
POWER.MSTPCR0.DMAC0 = ctx->clock;
|
||||
}
|
||||
|
||||
//---
|
||||
// Driver structure definition
|
||||
//---
|
||||
|
||||
gint_driver_t drv_dma = {
|
||||
.name = "DMA",
|
||||
.init = init,
|
||||
.ctx_size = sizeof(ctx_t),
|
||||
.sys_ctx = &sys_ctx,
|
||||
.ctx_save = ctx_save,
|
||||
.ctx_restore = ctx_restore,
|
||||
};
|
||||
|
||||
GINT_DECLARE_DRIVER(2, drv_dma);
|
32
src/dma/inth.s
Normal file
32
src/dma/inth.s
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
** gint:dma:inth - Interrupt handler for the DMA
|
||||
** An easy one, just clears some flags and marks all transfers as finished.
|
||||
*/
|
||||
|
||||
.global _inth_dma_dma0
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* DMA TRANSFER ENDED INTERRUPT HANDLER - BYTES */
|
||||
|
||||
_inth_dma_dma0:
|
||||
/* Clear the TE flag and DMA Enable in CHCR */
|
||||
mov.l 1f, r1
|
||||
mov.l @r1, r0
|
||||
mov #-4, r2
|
||||
and r2, r0
|
||||
mov.l r0, @r1
|
||||
|
||||
/* Clear the AE and NMIF flags in OR, and cut the master switch */
|
||||
add #0x34, r1
|
||||
mov.w @r1, r0
|
||||
shlr8 r0
|
||||
shll8 r0
|
||||
mov.w r0, @r1
|
||||
|
||||
rte
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
1: .long 0xfe00802c /* CHCR0 - OR is 0x34 bytes after this */
|
|
@ -2,11 +2,16 @@
|
|||
// gint:r61524 - Renesas R61524 driver
|
||||
//---
|
||||
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/defs/types.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/dma.h>
|
||||
#include <core/std.h>
|
||||
|
||||
#ifdef FXCG50
|
||||
|
||||
#define DMA SH7305_DMA
|
||||
#define POWER SH7305_POWER
|
||||
|
||||
//---
|
||||
// Device specification sheet
|
||||
//---
|
||||
|
@ -83,21 +88,39 @@ GINLINE static void write(uint16_t data)
|
|||
}
|
||||
|
||||
//---
|
||||
// Driver functions
|
||||
// Window management
|
||||
//---
|
||||
|
||||
void pixel(int ha, int va, int color)
|
||||
void r61524_win_get(uint16_t *HSA, uint16_t *HEA, uint16_t *VSA, uint16_t *VEA)
|
||||
{
|
||||
select(ram_address_horizontal);
|
||||
write(ha);
|
||||
select(horizontal_ram_start);
|
||||
*HSA = read();
|
||||
select(horizontal_ram_end);
|
||||
*HEA = read();
|
||||
|
||||
select(ram_address_vertical);
|
||||
write(va);
|
||||
|
||||
select(write_data);
|
||||
write(color);
|
||||
select(vertical_ram_start);
|
||||
*VSA = read();
|
||||
select(vertical_ram_end);
|
||||
*VEA = read();
|
||||
}
|
||||
|
||||
void r61524_win_set(uint16_t HSA, uint16_t HEA, uint16_t VSA, uint16_t VEA)
|
||||
{
|
||||
select(horizontal_ram_start);
|
||||
write(HSA);
|
||||
select(horizontal_ram_end);
|
||||
write(HEA);
|
||||
|
||||
select(vertical_ram_start);
|
||||
write(VSA);
|
||||
select(vertical_ram_end);
|
||||
write(VEA);
|
||||
}
|
||||
|
||||
//---
|
||||
// Driver functions
|
||||
//---
|
||||
|
||||
void r61524_test(void)
|
||||
{
|
||||
uint16_t device_name;
|
||||
|
@ -109,10 +132,6 @@ void r61524_test(void)
|
|||
uint16_t lpc;
|
||||
int VEM, COL;
|
||||
|
||||
uint32_t AD;
|
||||
uint16_t HSA, HEA;
|
||||
uint16_t VSA, VEA;
|
||||
|
||||
//---
|
||||
|
||||
select(device_code_read);
|
||||
|
@ -126,7 +145,7 @@ void r61524_test(void)
|
|||
{
|
||||
print(1, 2, "Aborting.");
|
||||
Bdisp_PutDisp_DD();
|
||||
delay(40);
|
||||
getkey();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -150,22 +169,6 @@ void r61524_test(void)
|
|||
VEM = (lpc >> 4) & 1;
|
||||
COL = lpc & 1;
|
||||
|
||||
/* Shift by 9, not 8, because of horizontal/vertical range inversion */
|
||||
select(ram_address_horizontal);
|
||||
AD = read();
|
||||
select(ram_address_vertical);
|
||||
AD |= read() << 9;
|
||||
|
||||
select(horizontal_ram_start);
|
||||
HSA = read();
|
||||
select(horizontal_ram_end);
|
||||
HEA = read();
|
||||
|
||||
select(vertical_ram_start);
|
||||
VSA = read();
|
||||
select(vertical_ram_end);
|
||||
VEA = read();
|
||||
|
||||
//---
|
||||
|
||||
print(15, 4, " SM=?");
|
||||
|
@ -194,62 +197,53 @@ void r61524_test(void)
|
|||
print_hex(12, 6, COL, 1);
|
||||
|
||||
Bdisp_PutDisp_DD();
|
||||
delay(50);
|
||||
getkey();
|
||||
|
||||
//---
|
||||
/* Bdisp_AllClr_VRAM();
|
||||
print(1, 1, "MSTPCR0=????????");
|
||||
print_hex(9, 1, POWER.MSTPCR0.lword, 8);
|
||||
|
||||
Bdisp_AllClr_VRAM();
|
||||
print(1, 2, "DMAOR=????");
|
||||
print_hex(7, 2, DMA.OR.word, 4);
|
||||
|
||||
print(1, 1, "Address=?????");
|
||||
print_hex(9, 1, AD, 5);
|
||||
|
||||
print(1, 2, "HSA=??? HEA=???");
|
||||
print_hex(5, 2, HSA, 3);
|
||||
print_hex(14, 2, HEA, 3);
|
||||
print(1, 3, "VSA=??? VEA=???");
|
||||
print_hex(5, 3, VSA, 3);
|
||||
print_hex(14, 3, VEA, 3);
|
||||
print(1, 3, "SAR=????????");
|
||||
print_hex(5, 3, DMA.DMA0.SAR, 8);
|
||||
print(1, 4, "DAR=????????");
|
||||
print_hex(5, 4, DMA.DMA0.DAR, 8);
|
||||
print(1, 5, "TCR=????????");
|
||||
print_hex(5, 5, DMA.DMA0.TCR, 8);
|
||||
print(1, 6, "CHCR=????????");
|
||||
print_hex(6, 6, DMA.DMA0.CHCR, 8);
|
||||
|
||||
Bdisp_PutDisp_DD();
|
||||
delay(50);
|
||||
getkey(); */
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Bdisp_AllClr_VRAM();
|
||||
Bdisp_PutDisp_DD();
|
||||
|
||||
//---
|
||||
|
||||
select(horizontal_ram_start);
|
||||
write(0);
|
||||
select(horizontal_ram_end);
|
||||
write(395);
|
||||
|
||||
select(vertical_ram_start);
|
||||
write(0);
|
||||
select(vertical_ram_end);
|
||||
write(223);
|
||||
|
||||
//---
|
||||
void r61524_dma_test(uint16_t *vram)
|
||||
{
|
||||
int y1 = 0;
|
||||
int height = 224;
|
||||
|
||||
/* Move the window to the desired region, then select address 0 */
|
||||
r61524_win_set(0, 395, y1, y1 + height - 1);
|
||||
select(ram_address_horizontal);
|
||||
write(HEA);
|
||||
write(0);
|
||||
select(ram_address_vertical);
|
||||
write(VSA);
|
||||
write(0);
|
||||
|
||||
/* Bind address 0xb4000000 to the data write command */
|
||||
select(write_data);
|
||||
|
||||
uint16_t color;
|
||||
for(int v = 0; v < 224; v++)
|
||||
for(int h = 0; h < 396; h++)
|
||||
{
|
||||
// int offset = 396 * v + h;
|
||||
// uint8_t *src = gimp_image.pixel_data + 2 * offset;
|
||||
color = 0x3eb7; // (src[1] << 8) | src[0];
|
||||
void *src = vram;
|
||||
void *dst = (void *)0xb4000000;
|
||||
|
||||
write(color);
|
||||
}
|
||||
/* The thing is, 396 is not a multiple of 32.
|
||||
To make things simple, we can choose to always send a multiple of 8
|
||||
rows, which makes the 32 factor appear. */
|
||||
int blocks = 198 * (height >> 3);
|
||||
|
||||
delay(200);
|
||||
dma_transfer(DMA_32B, blocks, src, DMA_INC, dst, DMA_FIXED);
|
||||
dma_transfer_wait();
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -269,33 +263,34 @@ GBSS static ctx_t sys_ctx;
|
|||
static void ctx_save(void *buf)
|
||||
{
|
||||
ctx_t *ctx = buf;
|
||||
|
||||
select(horizontal_ram_start);
|
||||
ctx->HSA = read();
|
||||
select(horizontal_ram_end);
|
||||
ctx->HEA = read();
|
||||
|
||||
select(vertical_ram_start);
|
||||
ctx->VSA = read();
|
||||
select(vertical_ram_end);
|
||||
ctx->VEA = read();
|
||||
r61524_win_get(&ctx->HSA, &ctx->HEA, &ctx->VSA, &ctx->VEA);
|
||||
}
|
||||
|
||||
static void ctx_restore(void *buf)
|
||||
{
|
||||
ctx_t *ctx = buf;
|
||||
|
||||
select(horizontal_ram_start);
|
||||
write(ctx->HSA);
|
||||
select(horizontal_ram_end);
|
||||
write(ctx->HEA);
|
||||
|
||||
select(vertical_ram_start);
|
||||
write(ctx->VSA);
|
||||
select(vertical_ram_end);
|
||||
write(ctx->VEA);
|
||||
r61524_win_set(ctx->HSA, ctx->HEA, ctx->VSA, ctx->VEA);
|
||||
}
|
||||
|
||||
//---
|
||||
// Driver status string
|
||||
//---
|
||||
|
||||
#ifdef GINT_BOOT_LOG
|
||||
|
||||
/* r6524_status() - status string */
|
||||
static const char *r6524_status(void)
|
||||
{
|
||||
select(device_code_read);
|
||||
uint16_t dev = read();
|
||||
|
||||
static char str[8];
|
||||
sprintf(str, "%4xF-b", dev);
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---
|
||||
// Driver structure definition
|
||||
//---
|
||||
|
@ -303,6 +298,7 @@ static void ctx_restore(void *buf)
|
|||
gint_driver_t drv_r61524 = {
|
||||
.name = "R61524",
|
||||
.init = NULL,
|
||||
.status = GINT_DRIVER_STATUS(r6524_status),
|
||||
.ctx_size = sizeof(ctx_t),
|
||||
.sys_ctx = &sys_ctx,
|
||||
.ctx_save = ctx_save,
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
** stop if the callback returns non-zero.
|
||||
*/
|
||||
|
||||
.global _inth_rtc_pri
|
||||
.global _inth_rtc_pri_helper
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
.global _inth_rtc_pri
|
||||
.global _inth_rtc_pri_helper
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* RTC PERIODIC INTERRUPT HANDLER - 56 BYTES */
|
||||
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
** from each interrupt handler to the next.
|
||||
*/
|
||||
|
||||
/* Gates for the standard Timer Unit (TMU) */
|
||||
.global _inth_tmu_0
|
||||
.global _inth_tmu_1
|
||||
.global _inth_tmu_2
|
||||
.global _inth_tmu_storage
|
||||
/* Gates for the standard Timer Unit (TMU) */
|
||||
.global _inth_tmu_0
|
||||
.global _inth_tmu_1
|
||||
.global _inth_tmu_2
|
||||
.global _inth_tmu_storage
|
||||
|
||||
/* Gates for the extra timers (informally called ETMU) */
|
||||
.global _inth_tmu_extra2
|
||||
.global _inth_tmu_extra_help
|
||||
.global _inth_tmu_extra_others
|
||||
/* Gates for the extra timers (informally called ETMU) */
|
||||
.global _inth_tmu_extra2
|
||||
.global _inth_tmu_extra_help
|
||||
.global _inth_tmu_extra_others
|
||||
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* TMU INTERRUPT HANDLERS - 128 BYTES
|
||||
Unfortunately I did not manage to write a handler that cleared the interrupt
|
||||
|
|
Loading…
Reference in a new issue