Добавить переносимый драйвер parallel NAND
This commit is contained in:
21
c/parallel-nand/ports/tms320f2812/README.md
Normal file
21
c/parallel-nand/ports/tms320f2812/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Порт TMS320F2812
|
||||
|
||||
Порт использует XINTF Zone 6:
|
||||
|
||||
- `XD0..XD7` — NAND `I/O0..I/O7`;
|
||||
- `XA0` — `CLE`;
|
||||
- `XA1` — `ALE`;
|
||||
- `XWE` — `WE#`;
|
||||
- `XRD` — `RE#`;
|
||||
- `XZCS6AND7` — `CE#`;
|
||||
- `GPIOE0/XINT1` — `R/B#` с внешней подтяжкой 4,7–10 кОм.
|
||||
|
||||
Адреса C28x задаются в 16-битных словах: data `0x100000`, command
|
||||
`0x100001`, address `0x100002`. Используется только младший байт XINTF.
|
||||
|
||||
`WP#` в базовом варианте аппаратный: для режима только чтения соединить с GND
|
||||
через 10 кОм; если позже понадобится PROGRAM/ERASE, заменить на GPIO и реализовать
|
||||
`tms_set_wp()`.
|
||||
|
||||
Задержка в порте приблизительная. После выбора частоты CPU проверить импульсы
|
||||
осциллографом и при необходимости изменить `PNAND_TMS_CPU_MHZ`.
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "parallel_nand_port_tms320f2812.h"
|
||||
#include "DSP281x_Device.h"
|
||||
|
||||
/* C28x addresses are 16-bit word addresses. XA0/XA1 drive CLE/ALE. */
|
||||
#define PNAND_TMS_DATA_REG (*(volatile unsigned int *)0x100000UL)
|
||||
#define PNAND_TMS_CMD_REG (*(volatile unsigned int *)0x100001UL)
|
||||
#define PNAND_TMS_ADDR_REG (*(volatile unsigned int *)0x100002UL)
|
||||
|
||||
#ifndef PNAND_TMS_CPU_MHZ
|
||||
#define PNAND_TMS_CPU_MHZ 150UL
|
||||
#endif
|
||||
|
||||
static void tms_delay_us(unsigned long us)
|
||||
{
|
||||
volatile unsigned long loops = us * (PNAND_TMS_CPU_MHZ / 5UL);
|
||||
while (loops-- != 0UL) asm(" NOP");
|
||||
}
|
||||
|
||||
static int tms_init(void)
|
||||
{
|
||||
EALLOW;
|
||||
GpioMuxRegs.GPEMUX.bit.XINT1_XBIO_GPIOE0 = 0;
|
||||
GpioMuxRegs.GPEDIR.bit.GPIOE0 = 0;
|
||||
|
||||
XintfRegs.XINTCNF2.bit.XTIMCLK = 1;
|
||||
XintfRegs.XINTCNF2.bit.WRBUFF = 0;
|
||||
XintfRegs.XINTCNF2.bit.CLKOFF = 0;
|
||||
XintfRegs.XINTCNF2.bit.CLKMODE = 1;
|
||||
XintfRegs.XTIMING6.bit.XWRLEAD = 3;
|
||||
XintfRegs.XTIMING6.bit.XWRACTIVE = 7;
|
||||
XintfRegs.XTIMING6.bit.XWRTRAIL = 3;
|
||||
XintfRegs.XTIMING6.bit.XRDLEAD = 3;
|
||||
XintfRegs.XTIMING6.bit.XRDACTIVE = 7;
|
||||
XintfRegs.XTIMING6.bit.XRDTRAIL = 3;
|
||||
XintfRegs.XTIMING6.bit.USEREADY = 0;
|
||||
XintfRegs.XTIMING6.bit.READYMODE = 0;
|
||||
XintfRegs.XTIMING6.bit.XSIZE = 3;
|
||||
EDIS;
|
||||
asm(" RPT #7 || NOP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tms_select(void) { /* XZCS6AND7 формируется каждым доступом. */ }
|
||||
static void tms_deselect(void) { }
|
||||
static void tms_write_command(pnand_octet_t v) { PNAND_TMS_CMD_REG = v & 0xFFU; }
|
||||
static void tms_write_address(pnand_octet_t v) { PNAND_TMS_ADDR_REG = v & 0xFFU; }
|
||||
static void tms_write_data(pnand_octet_t v) { PNAND_TMS_DATA_REG = v & 0xFFU; }
|
||||
static pnand_octet_t tms_read_data(void) { return PNAND_TMS_DATA_REG & 0xFFU; }
|
||||
static int tms_is_ready(void) { return GpioDataRegs.GPEDAT.bit.GPIOE0 != 0; }
|
||||
static void tms_set_wp(int enabled)
|
||||
{
|
||||
/* Шаблон платы фиксирует WP# аппаратно. См. README порта. */
|
||||
(void)enabled;
|
||||
}
|
||||
|
||||
static const parallel_nand_port_t tms_port = {
|
||||
tms_init, tms_select, tms_deselect,
|
||||
tms_write_command, tms_write_address, tms_write_data,
|
||||
tms_read_data, tms_is_ready, tms_set_wp, tms_delay_us
|
||||
};
|
||||
|
||||
const parallel_nand_port_t *parallel_nand_port_tms320f2812(void)
|
||||
{
|
||||
return &tms_port;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef PARALLEL_NAND_PORT_TMS320F2812_H
|
||||
#define PARALLEL_NAND_PORT_TMS320F2812_H
|
||||
|
||||
#include "parallel_nand_port.h"
|
||||
|
||||
const parallel_nand_port_t *parallel_nand_port_tms320f2812(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user