mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #6170 from hug-dev/cm3ds-update-drivers
CM3DS Maintenance Pull Request: Driver updates (4/4)pull/6169/head
commit
4139f13e31
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -23,11 +23,11 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef enum {
|
||||
UART_0 = (int)CMSDK_UART0_BASE, /* MCC UART */
|
||||
UART_1 = (int)CMSDK_UART1_BASE, /* MPS2+ UART */
|
||||
UART_2 = (int)CMSDK_UART2_BASE, /* Shield 0 UART */
|
||||
UART_3 = (int)CMSDK_UART3_BASE, /* Shield 1 UART */
|
||||
UART_4 = (int)CMSDK_UART4_BASE /* Shield BT UART */
|
||||
UART_0 = 0, /* MCC UART */
|
||||
UART_1, /* MPS2+ UART */
|
||||
UART_2, /* Shield 0 UART */
|
||||
UART_3, /* Shield 1 UART */
|
||||
UART_4 /* Shield BT UART */
|
||||
} UARTName;
|
||||
|
||||
typedef enum {
|
||||
|
@ -53,11 +53,12 @@ typedef enum {
|
|||
} ADCName;
|
||||
|
||||
typedef enum {
|
||||
SPI_0 = (int)MPS2_SSP0_BASE,
|
||||
SPI_1 = (int)MPS2_SSP1_BASE,
|
||||
SPI_2 = (int)MPS2_SSP2_BASE,
|
||||
SPI_3 = (int)MPS2_SSP3_BASE,
|
||||
SPI_4 = (int)MPS2_SSP4_BASE
|
||||
SPI_0 = 0,
|
||||
SPI_1,
|
||||
SPI_2,
|
||||
SPI_3,
|
||||
SPI_4,
|
||||
SPI_NC = (SPI_4 + 1)
|
||||
} SPIName;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file cmsdk_ticker.c
|
||||
* Two abstracted functionalities for CMSDK APB Timers
|
||||
* 1. Measure elapsed time
|
||||
* 2. Timer interval interrupt
|
||||
*
|
||||
* Passed \ref tick_drv_data_t should be initialized by the caller
|
||||
* for using these services accordingly.
|
||||
* See details \ref tick_cfg_t and \ref tick_data_t.
|
||||
*/
|
||||
|
||||
#include "cmsdk_ticker.h"
|
||||
|
||||
void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
if (!timer_data->data->is_initialized) {
|
||||
timer_cmsdk_init(timer_data->cfg->timer_driver);
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_cmsdk_enable_interrupt(timer_data->cfg->timer_driver);
|
||||
NVIC_EnableIRQ(timer_data->cfg->irq_n);
|
||||
|
||||
timer_data->data->max_interval_time =
|
||||
timer_data->cfg->convert_tick_to_time(TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
timer_data->data->is_initialized = true;
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
uint32_t current_elapsed = 0;
|
||||
|
||||
if (!timer_data->data->is_initialized) {
|
||||
cmsdk_ticker_init(timer_data);
|
||||
}
|
||||
current_elapsed = timer_cmsdk_get_elapsed_value(timer_data->cfg->timer_driver);
|
||||
/*
|
||||
* If for the same reload cycle (ie. cumulated_time is the same) the
|
||||
* current elapsed time is lower than the previous one, it means that the
|
||||
* timer has wrapped around without the system logging it. To ensure that
|
||||
* we are always returning an increasing time in those condition, we return
|
||||
* the time perviously read.
|
||||
*/
|
||||
if ((timer_data->data->previous_cumulated_time ==
|
||||
timer_data->data->cumulated_time) &&
|
||||
(current_elapsed < timer_data->data->previous_elapsed)) {
|
||||
current_elapsed = timer_data->data->previous_elapsed;
|
||||
}
|
||||
|
||||
timer_data->data->previous_elapsed = current_elapsed;
|
||||
timer_data->data->previous_cumulated_time =
|
||||
timer_data->data->cumulated_time;
|
||||
|
||||
return (timer_data->data->cumulated_time +
|
||||
timer_data->cfg->convert_tick_to_time(current_elapsed));
|
||||
}
|
||||
|
||||
void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
uint32_t interval = 0;
|
||||
uint32_t interval_reload_tick = 0;
|
||||
|
||||
/* Stop before read to avoid race condition with IRQ. */
|
||||
timer_cmsdk_disable(timer_data->cfg->timer_driver);
|
||||
uint32_t current_time = cmsdk_ticker_read(timer_data);
|
||||
|
||||
timer_data->data->interval_callback_enabled = true;
|
||||
|
||||
/*
|
||||
* We always assume that the event is in the future, even if this
|
||||
* substraction underflows it is still corect.
|
||||
*/
|
||||
interval = (timestamp - current_time);
|
||||
|
||||
if (interval >= timer_data->data->max_interval_time) {
|
||||
/* Event will be in the future but the time is too big: set max */
|
||||
interval_reload_tick = TIMER_CMSDK_MAX_RELOAD;
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
} else {
|
||||
/* Event will be in the future in a time that can be set */
|
||||
interval_reload_tick =
|
||||
timer_data->cfg->convert_time_to_tick(interval);
|
||||
timer_data->data->reload_time = interval;
|
||||
}
|
||||
|
||||
/* Store the current elapsed time, before reset the timer */
|
||||
timer_data->data->cumulated_time = current_time;
|
||||
/* Reset the timer with new reload value */
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
interval_reload_tick);
|
||||
timer_cmsdk_reset(timer_data->cfg->timer_driver);
|
||||
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
if (!timer_data->data->is_initialized) {
|
||||
cmsdk_ticker_init(timer_data);
|
||||
}
|
||||
|
||||
timer_data->data->interval_callback_enabled = false;
|
||||
|
||||
/* Stop before read to avoid race condition with IRQ. */
|
||||
timer_cmsdk_disable(timer_data->cfg->timer_driver);
|
||||
/* If interval interrupt is disabled, restore the default max interval,
|
||||
* but save the current elapsed time before changing the timer. */
|
||||
timer_data->data->cumulated_time = cmsdk_ticker_read(timer_data);
|
||||
/* Reset the timer with default reload value */
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
|
||||
timer_cmsdk_reset(timer_data->cfg->timer_driver);
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
NVIC_SetPendingIRQ(timer_data->cfg->irq_n);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
uint32_t reload_val = 0;
|
||||
/* If timer's internal interrupt status is not active, then not overflow,
|
||||
* but explicit interrupt request was fired by cmsdk_ticker_fire_interrupt.
|
||||
*/
|
||||
if (timer_cmsdk_is_interrupt_active(timer_data->cfg->timer_driver)) {
|
||||
/* 1. Calculate cumulated time by overflow */
|
||||
timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver);
|
||||
reload_val = timer_cmsdk_get_reload_value(timer_data->cfg->timer_driver);
|
||||
timer_data->data->cumulated_time +=
|
||||
timer_data->cfg->convert_tick_to_time(reload_val);
|
||||
}
|
||||
|
||||
/* 2. Call mbed interval interrupt handler if it's required */
|
||||
if (timer_data->data->interval_callback_enabled) {
|
||||
cmsdk_ticker_disable_interrupt(timer_data);
|
||||
timer_data->cfg->interval_callback();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file cmsdk_ticker.h
|
||||
* CMSDK Ticker implements the functionalities of mbed tickers:
|
||||
* 1. Elapsed time measurement
|
||||
* 2. Interval interrupt request
|
||||
*
|
||||
* This ticker service is based on CMSDK APB Timers, abstracting
|
||||
* the HAL logic, the timer driver and interrupt number.
|
||||
* These parameters should be passed to the functions by
|
||||
* an initialized \ref tick_drv_data_t pointer.
|
||||
*/
|
||||
|
||||
#ifndef CMSDK_TICKER_H
|
||||
#define CMSDK_TICKER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "CMSDK_CM3DS.h"
|
||||
#include "timer_cmsdk_drv.h"
|
||||
|
||||
#define SEC_TO_USEC_MULTIPLIER 1000000U
|
||||
|
||||
/**
|
||||
* brief Encapsulating struct for config data \ref tick_cfg_t and
|
||||
* the current status \ref tick_data_t.
|
||||
*/
|
||||
struct tick_drv_data_t {
|
||||
const struct tick_cfg_t* const cfg;
|
||||
struct tick_data_t* const data;
|
||||
};
|
||||
|
||||
/**
|
||||
* brief Configuration data of the CMSDK ticker
|
||||
*/
|
||||
struct tick_cfg_t {
|
||||
/** Pointer to the used CMSDK Timer's device structure */
|
||||
struct timer_cmsdk_dev_t* const timer_driver;
|
||||
/** IRQ number of the used CMSDK Timer */
|
||||
const IRQn_Type irq_n;
|
||||
/** Interval callback of mbed*/
|
||||
void (*const interval_callback)();
|
||||
/** Function pointers to call for conversions of clock ticks and defined
|
||||
* time unit.
|
||||
* These conversions define the unit of the measured time.
|
||||
*/
|
||||
uint32_t (*const convert_tick_to_time)(uint32_t tick);
|
||||
uint32_t (*const convert_time_to_tick)(uint32_t time);
|
||||
};
|
||||
|
||||
/**
|
||||
* brief Current state data of the CMSDK ticker
|
||||
*/
|
||||
struct tick_data_t {
|
||||
/** True if initialized the ticker, false otherwise */
|
||||
bool is_initialized;
|
||||
/** Measured elapsed time in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t cumulated_time;
|
||||
/** Max interval time possible to set, in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t max_interval_time;
|
||||
/** Current reload time in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t reload_time;
|
||||
/** Interval IRQ callback is requested */
|
||||
bool interval_callback_enabled;
|
||||
/** Previous cumulated time calculated for this ticker. Used in the
|
||||
* cmsdk_ticker_read function to detect that the timer has wrapped. */
|
||||
uint32_t previous_cumulated_time;
|
||||
/** Previous elapsed value for this ticker. Used in the
|
||||
* cmsdk_ticker_read function to detect that the timer has wrapped. */
|
||||
uint32_t previous_elapsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Init the CMSDK Ticker
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Read elapsed time by CMSDK Ticker
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*
|
||||
* \return Elapsed time in the unit defined by \ref convert_tick_to_time
|
||||
*/
|
||||
|
||||
uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Request interval interrupt by time stamp \ref timestamp_t
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
* \param[in] timestamp Absolute time \ref timestamp_t value when the interval
|
||||
* is requested. Unit of the timestamp is defined by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick
|
||||
*/
|
||||
void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data,
|
||||
uint32_t timestamp);
|
||||
|
||||
/**
|
||||
* \brief Disable interval interrupt
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Clear interval interrupt
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Set pending interrupt that should be fired right away.
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Interrupt handler of the given CMSDK Timer
|
||||
*
|
||||
* \warning This function may be called from multiple interrupt handlers,
|
||||
* so extra care must be taken for re-entrancy!
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data);
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2009-2018 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
@ -135,420 +135,6 @@ typedef enum IRQn
|
|||
#warning Not supported compiler type
|
||||
#endif
|
||||
|
||||
/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */
|
||||
__IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */
|
||||
__IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
|
||||
};
|
||||
__IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */
|
||||
|
||||
} CMSDK_UART_TypeDef;
|
||||
|
||||
/* CMSDK_UART DATA Register Definitions */
|
||||
|
||||
#define CMSDK_UART_DATA_Pos 0 /* CMSDK_UART_DATA_Pos: DATA Position */
|
||||
#define CMSDK_UART_DATA_Msk (0xFFul << CMSDK_UART_DATA_Pos) /* CMSDK_UART DATA: DATA Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXOR_Pos 3 /* CMSDK_UART STATE: RXOR Position */
|
||||
#define CMSDK_UART_STATE_RXOR_Msk (0x1ul << CMSDK_UART_STATE_RXOR_Pos) /* CMSDK_UART STATE: RXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXOR_Pos 2 /* CMSDK_UART STATE: TXOR Position */
|
||||
#define CMSDK_UART_STATE_TXOR_Msk (0x1ul << CMSDK_UART_STATE_TXOR_Pos) /* CMSDK_UART STATE: TXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXBF_Pos 1 /* CMSDK_UART STATE: RXBF Position */
|
||||
#define CMSDK_UART_STATE_RXBF_Msk (0x1ul << CMSDK_UART_STATE_RXBF_Pos) /* CMSDK_UART STATE: RXBF Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXBF_Pos 0 /* CMSDK_UART STATE: TXBF Position */
|
||||
#define CMSDK_UART_STATE_TXBF_Msk (0x1ul << CMSDK_UART_STATE_TXBF_Pos ) /* CMSDK_UART STATE: TXBF Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_HSTM_Pos 6 /* CMSDK_UART CTRL: HSTM Position */
|
||||
#define CMSDK_UART_CTRL_HSTM_Msk (0x01ul << CMSDK_UART_CTRL_HSTM_Pos) /* CMSDK_UART CTRL: HSTM Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Pos 5 /* CMSDK_UART CTRL: RXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXORIRQEN_Pos) /* CMSDK_UART CTRL: RXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Pos 4 /* CMSDK_UART CTRL: TXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXORIRQEN_Pos) /* CMSDK_UART CTRL: TXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Pos 3 /* CMSDK_UART CTRL: RXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXIRQEN_Pos) /* CMSDK_UART CTRL: RXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Pos 2 /* CMSDK_UART CTRL: TXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXIRQEN_Pos) /* CMSDK_UART CTRL: TXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXEN_Pos 1 /* CMSDK_UART CTRL: RXEN Position */
|
||||
#define CMSDK_UART_CTRL_RXEN_Msk (0x01ul << CMSDK_UART_CTRL_RXEN_Pos) /* CMSDK_UART CTRL: RXEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXEN_Pos 0 /* CMSDK_UART CTRL: TXEN Position */
|
||||
#define CMSDK_UART_CTRL_TXEN_Msk (0x01ul << CMSDK_UART_CTRL_TXEN_Pos) /* CMSDK_UART CTRL: TXEN Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Pos 3 /* CMSDK_UART CTRL: RXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXORIRQ_Pos) /* CMSDK_UART CTRL: RXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Pos 2 /* CMSDK_UART CTRL: TXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXORIRQ_Pos) /* CMSDK_UART CTRL: TXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Pos 1 /* CMSDK_UART CTRL: RXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXIRQ_Pos) /* CMSDK_UART CTRL: RXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Pos 0 /* CMSDK_UART CTRL: TXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXIRQ_Pos) /* CMSDK_UART CTRL: TXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */
|
||||
#define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */
|
||||
|
||||
|
||||
/*----------------------------- Timer (TIMER) -------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CTRL; /* Offset: 0x000 (R/W) Control Register */
|
||||
__IO uint32_t VALUE; /* Offset: 0x004 (R/W) Current Value Register */
|
||||
__IO uint32_t RELOAD; /* Offset: 0x008 (R/W) Reload Value Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
|
||||
};
|
||||
|
||||
} CMSDK_TIMER_TypeDef;
|
||||
|
||||
/* CMSDK_TIMER CTRL Register Definitions */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_IRQEN_Pos 3 /* CMSDK_TIMER CTRL: IRQEN Position */
|
||||
#define CMSDK_TIMER_CTRL_IRQEN_Msk (0x01ul << CMSDK_TIMER_CTRL_IRQEN_Pos) /* CMSDK_TIMER CTRL: IRQEN Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_SELEXTCLK_Pos 2 /* CMSDK_TIMER CTRL: SELEXTCLK Position */
|
||||
#define CMSDK_TIMER_CTRL_SELEXTCLK_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTCLK_Pos) /* CMSDK_TIMER CTRL: SELEXTCLK Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_SELEXTEN_Pos 1 /* CMSDK_TIMER CTRL: SELEXTEN Position */
|
||||
#define CMSDK_TIMER_CTRL_SELEXTEN_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTEN_Pos) /* CMSDK_TIMER CTRL: SELEXTEN Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_EN_Pos 0 /* CMSDK_TIMER CTRL: EN Position */
|
||||
#define CMSDK_TIMER_CTRL_EN_Msk (0x01ul << CMSDK_TIMER_CTRL_EN_Pos) /* CMSDK_TIMER CTRL: EN Mask */
|
||||
|
||||
#define CMSDK_TIMER_VAL_CURRENT_Pos 0 /* CMSDK_TIMER VALUE: CURRENT Position */
|
||||
#define CMSDK_TIMER_VAL_CURRENT_Msk (0xFFFFFFFFul << CMSDK_TIMER_VAL_CURRENT_Pos) /* CMSDK_TIMER VALUE: CURRENT Mask */
|
||||
|
||||
#define CMSDK_TIMER_RELOAD_VAL_Pos 0 /* CMSDK_TIMER RELOAD: RELOAD Position */
|
||||
#define CMSDK_TIMER_RELOAD_VAL_Msk (0xFFFFFFFFul << CMSDK_TIMER_RELOAD_VAL_Pos) /* CMSDK_TIMER RELOAD: RELOAD Mask */
|
||||
|
||||
#define CMSDK_TIMER_INTSTATUS_Pos 0 /* CMSDK_TIMER INTSTATUS: INTSTATUSPosition */
|
||||
#define CMSDK_TIMER_INTSTATUS_Msk (0x01ul << CMSDK_TIMER_INTSTATUS_Pos) /* CMSDK_TIMER INTSTATUS: INTSTATUSMask */
|
||||
|
||||
#define CMSDK_TIMER_INTCLEAR_Pos 0 /* CMSDK_TIMER INTCLEAR: INTCLEAR Position */
|
||||
#define CMSDK_TIMER_INTCLEAR_Msk (0x01ul << CMSDK_TIMER_INTCLEAR_Pos) /* CMSDK_TIMER INTCLEAR: INTCLEAR Mask */
|
||||
|
||||
|
||||
/*------------- Timer (TIM) --------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t Timer1Load; /* Offset: 0x000 (R/W) Timer 1 Load */
|
||||
__I uint32_t Timer1Value; /* Offset: 0x004 (R/ ) Timer 1 Counter Current Value */
|
||||
__IO uint32_t Timer1Control; /* Offset: 0x008 (R/W) Timer 1 Control */
|
||||
__O uint32_t Timer1IntClr; /* Offset: 0x00C ( /W) Timer 1 Interrupt Clear */
|
||||
__I uint32_t Timer1RIS; /* Offset: 0x010 (R/ ) Timer 1 Raw Interrupt Status */
|
||||
__I uint32_t Timer1MIS; /* Offset: 0x014 (R/ ) Timer 1 Masked Interrupt Status */
|
||||
__IO uint32_t Timer1BGLoad; /* Offset: 0x018 (R/W) Background Load Register */
|
||||
uint32_t RESERVED0;
|
||||
__IO uint32_t Timer2Load; /* Offset: 0x020 (R/W) Timer 2 Load */
|
||||
__I uint32_t Timer2Value; /* Offset: 0x024 (R/ ) Timer 2 Counter Current Value */
|
||||
__IO uint32_t Timer2Control; /* Offset: 0x028 (R/W) Timer 2 Control */
|
||||
__O uint32_t Timer2IntClr; /* Offset: 0x02C ( /W) Timer 2 Interrupt Clear */
|
||||
__I uint32_t Timer2RIS; /* Offset: 0x030 (R/ ) Timer 2 Raw Interrupt Status */
|
||||
__I uint32_t Timer2MIS; /* Offset: 0x034 (R/ ) Timer 2 Masked Interrupt Status */
|
||||
__IO uint32_t Timer2BGLoad; /* Offset: 0x038 (R/W) Background Load Register */
|
||||
uint32_t RESERVED1[945];
|
||||
__IO uint32_t ITCR; /* Offset: 0xF00 (R/W) Integration Test Control Register */
|
||||
__O uint32_t ITOP; /* Offset: 0xF04 ( /W) Integration Test Output Set Register */
|
||||
} CMSDK_DUALTIMER_BOTH_TypeDef;
|
||||
|
||||
#define CMSDK_DUALTIMER1_LOAD_Pos 0 /* CMSDK_DUALTIMER1 LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER1_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_LOAD_Pos) /* CMSDK_DUALTIMER1 LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_VALUE_Pos 0 /* CMSDK_DUALTIMER1 VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER1_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_VALUE_Pos) /* CMSDK_DUALTIMER1 VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_EN_Pos) /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_MODE_Pos) /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_INTCLR_Pos 0 /* CMSDK_DUALTIMER1 INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER1_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER1_INTCLR_Pos) /* CMSDK_DUALTIMER1 INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER1_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER1_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_BGLOAD_Pos 0 /* CMSDK_DUALTIMER1 BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER1_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_BGLOAD_Pos) /* CMSDK_DUALTIMER1 BGLOAD: Background Load Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_LOAD_Pos 0 /* CMSDK_DUALTIMER2 LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER2_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_LOAD_Pos) /* CMSDK_DUALTIMER2 LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_VALUE_Pos 0 /* CMSDK_DUALTIMER2 VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER2_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_VALUE_Pos) /* CMSDK_DUALTIMER2 VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_EN_Pos) /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_MODE_Pos) /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_INTCLR_Pos 0 /* CMSDK_DUALTIMER2 INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER2_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER2_INTCLR_Pos) /* CMSDK_DUALTIMER2 INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER2_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER2_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_BGLOAD_Pos 0 /* CMSDK_DUALTIMER2 BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER2_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_BGLOAD_Pos) /* CMSDK_DUALTIMER2 BGLOAD: Background Load Mask */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t TimerLoad; /* Offset: 0x000 (R/W) Timer Load */
|
||||
__I uint32_t TimerValue; /* Offset: 0x000 (R/W) Timer Counter Current Value */
|
||||
__IO uint32_t TimerControl; /* Offset: 0x000 (R/W) Timer Control */
|
||||
__O uint32_t TimerIntClr; /* Offset: 0x000 (R/W) Timer Interrupt Clear */
|
||||
__I uint32_t TimerRIS; /* Offset: 0x000 (R/W) Timer Raw Interrupt Status */
|
||||
__I uint32_t TimerMIS; /* Offset: 0x000 (R/W) Timer Masked Interrupt Status */
|
||||
__IO uint32_t TimerBGLoad; /* Offset: 0x000 (R/W) Background Load Register */
|
||||
} CMSDK_DUALTIMER_SINGLE_TypeDef;
|
||||
|
||||
#define CMSDK_DUALTIMER_LOAD_Pos 0 /* CMSDK_DUALTIMER LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_LOAD_Pos) /* CMSDK_DUALTIMER LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_VALUE_Pos 0 /* CMSDK_DUALTIMER VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_VALUE_Pos) /* CMSDK_DUALTIMER VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_EN_Pos) /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_MODE_Pos) /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_INTCLR_Pos 0 /* CMSDK_DUALTIMER INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER_INTCLR_Pos) /* CMSDK_DUALTIMER INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_BGLOAD_Pos 0 /* CMSDK_DUALTIMER BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_BGLOAD_Pos) /* CMSDK_DUALTIMER BGLOAD: Background Load Mask */
|
||||
|
||||
|
||||
/*-------------------- General Purpose Input Output (GPIO) -------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t DATA; /* Offset: 0x000 (R/W) DATA Register */
|
||||
__IO uint32_t DATAOUT; /* Offset: 0x004 (R/W) Data Output Latch Register */
|
||||
uint32_t RESERVED0[2];
|
||||
__IO uint32_t OUTENABLESET; /* Offset: 0x010 (R/W) Output Enable Set Register */
|
||||
__IO uint32_t OUTENABLECLR; /* Offset: 0x014 (R/W) Output Enable Clear Register */
|
||||
__IO uint32_t ALTFUNCSET; /* Offset: 0x018 (R/W) Alternate Function Set Register */
|
||||
__IO uint32_t ALTFUNCCLR; /* Offset: 0x01C (R/W) Alternate Function Clear Register */
|
||||
__IO uint32_t INTENSET; /* Offset: 0x020 (R/W) Interrupt Enable Set Register */
|
||||
__IO uint32_t INTENCLR; /* Offset: 0x024 (R/W) Interrupt Enable Clear Register */
|
||||
__IO uint32_t INTTYPESET; /* Offset: 0x028 (R/W) Interrupt Type Set Register */
|
||||
__IO uint32_t INTTYPECLR; /* Offset: 0x02C (R/W) Interrupt Type Clear Register */
|
||||
__IO uint32_t INTPOLSET; /* Offset: 0x030 (R/W) Interrupt Polarity Set Register */
|
||||
__IO uint32_t INTPOLCLR; /* Offset: 0x034 (R/W) Interrupt Polarity Clear Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x038 (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x038 ( /W) Interrupt Clear Register */
|
||||
};
|
||||
uint32_t RESERVED1[241];
|
||||
__IO uint32_t LB_MASKED[256]; /* Offset: 0x400 - 0x7FC Lower byte Masked Access Register (R/W) */
|
||||
__IO uint32_t UB_MASKED[256]; /* Offset: 0x800 - 0xBFC Upper byte Masked Access Register (R/W) */
|
||||
} CMSDK_GPIO_TypeDef;
|
||||
|
||||
#define CMSDK_GPIO_DATA_Pos 0 /* CMSDK_GPIO DATA: DATA Position */
|
||||
#define CMSDK_GPIO_DATA_Msk (0xFFFFul << CMSDK_GPIO_DATA_Pos) /* CMSDK_GPIO DATA: DATA Mask */
|
||||
|
||||
#define CMSDK_GPIO_DATAOUT_Pos 0 /* CMSDK_GPIO DATAOUT: DATAOUT Position */
|
||||
#define CMSDK_GPIO_DATAOUT_Msk (0xFFFFul << CMSDK_GPIO_DATAOUT_Pos) /* CMSDK_GPIO DATAOUT: DATAOUT Mask */
|
||||
|
||||
#define CMSDK_GPIO_OUTENSET_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */
|
||||
#define CMSDK_GPIO_OUTENSET_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_OUTENCLR_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */
|
||||
#define CMSDK_GPIO_OUTENCLR_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNCSET_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */
|
||||
#define CMSDK_GPIO_ALTFUNCSET_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNCCLR_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */
|
||||
#define CMSDK_GPIO_ALTFUNCCLR_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTENSET_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */
|
||||
#define CMSDK_GPIO_INTENSET_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTENCLR_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */
|
||||
#define CMSDK_GPIO_INTENCLR_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTTYPESET_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */
|
||||
#define CMSDK_GPIO_INTTYPESET_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTTYPECLR_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */
|
||||
#define CMSDK_GPIO_INTTYPECLR_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTPOLSET_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */
|
||||
#define CMSDK_GPIO_INTPOLSET_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTPOLCLR_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */
|
||||
#define CMSDK_GPIO_INTPOLCLR_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTSTATUS_Pos 0 /* CMSDK_GPIO INTSTATUS: INTSTATUS Position */
|
||||
#define CMSDK_GPIO_INTSTATUS_Msk (0xFFul << CMSDK_GPIO_INTSTATUS_Pos) /* CMSDK_GPIO INTSTATUS: INTSTATUS Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTCLEAR_Pos 0 /* CMSDK_GPIO INTCLEAR: INTCLEAR Position */
|
||||
#define CMSDK_GPIO_INTCLEAR_Msk (0xFFul << CMSDK_GPIO_INTCLEAR_Pos) /* CMSDK_GPIO INTCLEAR: INTCLEAR Mask */
|
||||
|
||||
#define CMSDK_GPIO_MASKLOWBYTE_Pos 0 /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Position */
|
||||
#define CMSDK_GPIO_MASKLOWBYTE_Msk (0x00FFul << CMSDK_GPIO_MASKLOWBYTE_Pos) /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Mask */
|
||||
|
||||
#define CMSDK_GPIO_MASKHIGHBYTE_Pos 0 /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Position */
|
||||
#define CMSDK_GPIO_MASKHIGHBYTE_Msk (0xFF00ul << CMSDK_GPIO_MASKHIGHBYTE_Pos) /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Mask */
|
||||
|
||||
/* GPIO Alternate function pin numbers */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX 0 /* Shield 0 UART 2 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX % 16)
|
||||
#define CMSDK_GPIO_SH0_UART2_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX 4 /* Shield 0 UART 2 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX % 16)
|
||||
#define CMSDK_GPIO_SH0_UART2_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX 26 /* Shield 1 UART 3 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX % 16)
|
||||
#define CMSDK_GPIO_SH1_UART3_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX 30 /* Shield 1 UART 3 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX % 16)
|
||||
#define CMSDK_GPIO_SH1_UART3_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_RX 23 /* UART 4 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_RX_SET (CMSDK_GPIO_ALTFUNC_UART4_RX % 16)
|
||||
#define CMSDK_GPIO_UART4_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_TX 24 /* UART 4 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_TX_SET (CMSDK_GPIO_ALTFUNC_UART4_TX % 16)
|
||||
#define CMSDK_GPIO_UART4_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C 5 /* Shield 0 SCL I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C % 16)
|
||||
#define CMSDK_GPIO_SH0_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C 15 /* Shield 0 SDA I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C % 16)
|
||||
#define CMSDK_GPIO_SH0_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C 31 /* Shield 1 SCL I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C % 16)
|
||||
#define CMSDK_GPIO_SH1_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C 41 /* Shield 1 SDA I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C % 16)
|
||||
#define CMSDK_GPIO_SH1_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI 11 /* Shield 0 SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI 12 /* Shield 0 CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI 13 /* Shield 0 MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI 14 /* Shield 0 MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI 44 /* Shield 1 SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI 38 /* Shield 1 CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI 39 /* Shield 1 MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI 40 /* Shield 1 MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI 19 /* Shield ADC SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI 16 /* Shield ADC CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI 18 /* Shield ADC MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI 17 /* Shield ADC MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI / 16)
|
||||
|
||||
/*------------- System Control (SYSCON) --------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
|
@ -755,28 +341,12 @@ typedef struct
|
|||
/* ================ Peripheral declaration ================ */
|
||||
/* ================================================================================ */
|
||||
|
||||
#define CMSDK_UART0 ((CMSDK_UART_TypeDef *) CMSDK_UART0_BASE )
|
||||
#define CMSDK_UART1 ((CMSDK_UART_TypeDef *) CMSDK_UART1_BASE )
|
||||
#define CMSDK_UART2 ((CMSDK_UART_TypeDef *) CMSDK_UART2_BASE )
|
||||
#define CMSDK_UART3 ((CMSDK_UART_TypeDef *) CMSDK_UART3_BASE )
|
||||
#define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE )
|
||||
#define CMSDK_TIMER0 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER0_BASE )
|
||||
#define CMSDK_TIMER1 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER1_BASE )
|
||||
#define CMSDK_DUALTIMER ((CMSDK_DUALTIMER_BOTH_TypeDef *) CMSDK_DUALTIMER_BASE )
|
||||
#define CMSDK_DUALTIMER1 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_1_BASE )
|
||||
#define CMSDK_DUALTIMER2 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_2_BASE )
|
||||
#define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE )
|
||||
#define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE )
|
||||
#define CMSDK_GPIO0 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO0_BASE )
|
||||
#define CMSDK_GPIO1 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO1_BASE )
|
||||
#define CMSDK_GPIO2 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO2_BASE )
|
||||
#define CMSDK_GPIO3 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO3_BASE )
|
||||
#define CMSDK_GPIO4 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO4_BASE )
|
||||
#define CMSDK_GPIO5 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO5_BASE )
|
||||
#define CMSDK_SYSCON ((CMSDK_SYSCON_TypeDef *) CMSDK_SYSCTRL_BASE )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMSDK_BEETLE_H */
|
||||
#endif /* CMSDK_CM3DS_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* MPS2 CMSIS Library
|
||||
*
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -153,154 +153,6 @@ typedef struct //
|
|||
} MPS2_SCC_TypeDef;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* SSP Peripheral declaration */
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct // Document DDI0194G_ssp_pl022_r1p3_trm.pdf
|
||||
{
|
||||
__IO uint32_t CR0; // Offset: 0x000 (R/W) Control register 0
|
||||
// [31:16] : Reserved
|
||||
// [15:8] : Serial clock rate
|
||||
// [7] : SSPCLKOUT phase, applicable to Motorola SPI frame format only
|
||||
// [6] : SSPCLKOUT polarity, applicable to Motorola SPI frame format only
|
||||
// [5:4] : Frame format
|
||||
// [3:0] : Data Size Select
|
||||
__IO uint32_t CR1; // Offset: 0x004 (R/W) Control register 1
|
||||
// [31:4] : Reserved
|
||||
// [3] : Slave-mode output disable
|
||||
// [2] : Master or slave mode select
|
||||
// [1] : Synchronous serial port enable
|
||||
// [0] : Loop back mode
|
||||
__IO uint32_t DR; // Offset: 0x008 (R/W) Data register
|
||||
// [31:16] : Reserved
|
||||
// [15:0] : Transmit/Receive FIFO
|
||||
__I uint32_t SR; // Offset: 0x00C (R/ ) Status register
|
||||
// [31:5] : Reserved
|
||||
// [4] : PrimeCell SSP busy flag
|
||||
// [3] : Receive FIFO full
|
||||
// [2] : Receive FIFO not empty
|
||||
// [1] : Transmit FIFO not full
|
||||
// [0] : Transmit FIFO empty
|
||||
__IO uint32_t CPSR; // Offset: 0x010 (R/W) Clock prescale register
|
||||
// [31:8] : Reserved
|
||||
// [8:0] : Clock prescale divisor
|
||||
__IO uint32_t IMSC; // Offset: 0x014 (R/W) Interrupt mask set or clear register
|
||||
// [31:4] : Reserved
|
||||
// [3] : Transmit FIFO interrupt mask
|
||||
// [2] : Receive FIFO interrupt mask
|
||||
// [1] : Receive timeout interrupt mask
|
||||
// [0] : Receive overrun interrupt mask
|
||||
__I uint32_t RIS; // Offset: 0x018 (R/ ) Raw interrupt status register
|
||||
// [31:4] : Reserved
|
||||
// [3] : raw interrupt state, prior to masking, of the SSPTXINTR interrupt
|
||||
// [2] : raw interrupt state, prior to masking, of the SSPRXINTR interrupt
|
||||
// [1] : raw interrupt state, prior to masking, of the SSPRTINTR interrupt
|
||||
// [0] : raw interrupt state, prior to masking, of the SSPRORINTR interrupt
|
||||
__I uint32_t MIS; // Offset: 0x01C (R/ ) Masked interrupt status register
|
||||
// [31:4] : Reserved
|
||||
// [3] : transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt
|
||||
// [2] : receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt
|
||||
// [1] : receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt
|
||||
// [0] : receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt
|
||||
__O uint32_t ICR; // Offset: 0x020 ( /W) Interrupt clear register
|
||||
// [31:2] : Reserved
|
||||
// [1] : Clears the SSPRTINTR interrupt
|
||||
// [0] : Clears the SSPRORINTR interrupt
|
||||
__IO uint32_t DMACR; // Offset: 0x024 (R/W) DMA control register
|
||||
// [31:2] : Reserved
|
||||
// [1] : Transmit DMA Enable
|
||||
// [0] : Receive DMA Enable
|
||||
} MPS2_SSP_TypeDef;
|
||||
|
||||
|
||||
// SSP_CR0 Control register 0
|
||||
#define SSP_CR0_DSS_Pos 0 // Data Size Select
|
||||
#define SSP_CR0_DSS_Msk (0xF<<SSP_CR0_DSS_Pos)
|
||||
#define SSP_CR0_FRF_Pos 4 // Frame Format Select
|
||||
#define SSP_CR0_FRF_Msk (3UL<<SSP_CR0_FRM_Pos)
|
||||
#define SSP_CR0_SPO_Pos 6 // SSPCLKOUT polarity
|
||||
#define SSP_CR0_SPO_Msk (1UL<<SSP_CR0_SPO_Pos)
|
||||
#define SSP_CR0_SPH_Pos 7 // SSPCLKOUT phase
|
||||
#define SSP_CR0_SPH_Msk (1UL<<SSP_CR0_SPH_Pos)
|
||||
#define SSP_CR0_SCR_Pos 8 // Serial Clock Rate (divide)
|
||||
#define SSP_CR0_SCR_Msk (0xFF<<SSP_CR0_SCR_Pos)
|
||||
|
||||
#define SSP_CR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3
|
||||
#define SSP_CR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define SSP_CR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define SSP_CR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// SSP_CR1 Control register 1
|
||||
#define SSP_CR1_LBM_Pos 0 // Loop Back Mode
|
||||
#define SSP_CR1_LBM_Msk (1UL<<SSP_CR1_LBM_Pos)
|
||||
#define SSP_CR1_SSE_Pos 1 // Serial port enable
|
||||
#define SSP_CR1_SSE_Msk (1UL<<SSP_CR1_SSE_Pos)
|
||||
#define SSP_CR1_MS_Pos 2 // Master or Slave mode
|
||||
#define SSP_CR1_MS_Msk (1UL<<SSP_CR1_MS_Pos)
|
||||
#define SSP_CR1_SOD_Pos 3 // Slave Output mode Disable
|
||||
#define SSP_CR1_SOD_Msk (1UL<<SSP_CR1_SOD_Pos)
|
||||
|
||||
// SSP_SR Status register
|
||||
#define SSP_SR_TFE_Pos 0 // Transmit FIFO empty
|
||||
#define SSP_SR_TFE_Msk (1UL<<SSP_SR_TFE_Pos)
|
||||
#define SSP_SR_TNF_Pos 1 // Transmit FIFO not full
|
||||
#define SSP_SR_TNF_Msk (1UL<<SSP_SR_TNF_Pos)
|
||||
#define SSP_SR_RNE_Pos 2 // Receive FIFO not empty
|
||||
#define SSP_SR_RNE_Msk (1UL<<SSP_SR_RNE_Pos)
|
||||
#define SSP_SR_RFF_Pos 3 // Receive FIFO full
|
||||
#define SSP_SR_RFF_Msk (1UL<<SSP_SR_RFF_Pos)
|
||||
#define SSP_SR_BSY_Pos 4 // Busy
|
||||
#define SSP_SR_BSY_Msk (1UL<<SSP_SR_BSY_Pos)
|
||||
|
||||
// SSP_CPSR Clock prescale register
|
||||
#define SSP_CPSR_CPD_Pos 0 // Clock prescale divisor
|
||||
#define SSP_CPSR_CPD_Msk (0xFF<<SSP_CPSR_CDP_Pos)
|
||||
|
||||
#define SSP_CPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8
|
||||
|
||||
// SSPIMSC Interrupt mask set and clear register
|
||||
#define SSP_IMSC_RORIM_Pos 0 // Receive overrun not Masked
|
||||
#define SSP_IMSC_RORIM_Msk (1UL<<SSP_IMSC_RORIM_Pos)
|
||||
#define SSP_IMSC_RTIM_Pos 1 // Receive timeout not Masked
|
||||
#define SSP_IMSC_RTIM_Msk (1UL<<SSP_IMSC_RTIM_Pos)
|
||||
#define SSP_IMSC_RXIM_Pos 2 // Receive FIFO not Masked
|
||||
#define SSP_IMSC_RXIM_Msk (1UL<<SSP_IMSC_RXIM_Pos)
|
||||
#define SSP_IMSC_TXIM_Pos 3 // Transmit FIFO not Masked
|
||||
#define SSP_IMSC_TXIM_Msk (1UL<<SSP_IMSC_TXIM_Pos)
|
||||
|
||||
// SSPRIS Raw interrupt status register
|
||||
#define SSP_RIS_RORRIS_Pos 0 // Raw Overrun interrupt flag
|
||||
#define SSP_RIS_RORRIS_Msk (1UL<<SSP_RIS_RORRIS_Pos)
|
||||
#define SSP_RIS_RTRIS_Pos 1 // Raw Timemout interrupt flag
|
||||
#define SSP_RIS_RTRIS_Msk (1UL<<SSP_RIS_RTRIS_Pos)
|
||||
#define SSP_RIS_RXRIS_Pos 2 // Raw Receive interrupt flag
|
||||
#define SSP_RIS_RXRIS_Msk (1UL<<SSP_RIS_RXRIS_Pos)
|
||||
#define SSP_RIS_TXRIS_Pos 3 // Raw Transmit interrupt flag
|
||||
#define SSP_RIS_TXRIS_Msk (1UL<<SSP_RIS_TXRIS_Pos)
|
||||
|
||||
// SSPMIS Masked interrupt status register
|
||||
#define SSP_MIS_RORMIS_Pos 0 // Masked Overrun interrupt flag
|
||||
#define SSP_MIS_RORMIS_Msk (1UL<<SSP_MIS_RORMIS_Pos)
|
||||
#define SSP_MIS_RTMIS_Pos 1 // Masked Timemout interrupt flag
|
||||
#define SSP_MIS_RTMIS_Msk (1UL<<SSP_MIS_RTMIS_Pos)
|
||||
#define SSP_MIS_RXMIS_Pos 2 // Masked Receive interrupt flag
|
||||
#define SSP_MIS_RXMIS_Msk (1UL<<SSP_MIS_RXMIS_Pos)
|
||||
#define SSP_MIS_TXMIS_Pos 3 // Masked Transmit interrupt flag
|
||||
#define SSP_MIS_TXMIS_Msk (1UL<<SSP_MIS_TXMIS_Pos)
|
||||
|
||||
// SSPICR Interrupt clear register
|
||||
#define SSP_ICR_RORIC_Pos 0 // Clears Overrun interrupt flag
|
||||
#define SSP_ICR_RORIC_Msk (1UL<<SSP_ICR_RORIC_Pos)
|
||||
#define SSP_ICR_RTIC_Pos 1 // Clears Timemout interrupt flag
|
||||
#define SSP_ICR_RTIC_Msk (1UL<<SSP_ICR_RTIC_Pos)
|
||||
|
||||
// SSPDMACR DMA control register
|
||||
#define SSP_DMACR_RXDMAE_Pos 0 // Enable Receive FIFO DMA
|
||||
#define SSP_DMACR_RXDMAE_Msk (1UL<<SSP_DMACR_RXDMAE_Pos)
|
||||
#define SSP_DMACR_TXDMAE_Pos 1 // Enable Transmit FIFO DMA
|
||||
#define SSP_DMACR_TXDMAE_Msk (1UL<<SSP_DMACR_TXDMAE_Pos)
|
||||
|
||||
/******************************************************************************/
|
||||
/* Audio and Touch Screen (I2C) Peripheral declaration */
|
||||
/******************************************************************************/
|
||||
|
@ -577,11 +429,6 @@ __IO uint32_t E2P_DATA; // EEPROM Data (offset 0xB4)
|
|||
#define MPS2_AAIC_I2S ((MPS2_I2S_TypeDef *) MPS2_AAIC_I2S_BASE )
|
||||
#define MPS2_FPGAIO ((MPS2_FPGAIO_TypeDef *) MPS2_FPGAIO_BASE )
|
||||
#define MPS2_SCC ((MPS2_SCC_TypeDef *) MPS2_SCC_BASE )
|
||||
#define MPS2_SSP0 ((MPS2_SSP_TypeDef *) MPS2_SSP0_BASE )
|
||||
#define MPS2_SSP1 ((MPS2_SSP_TypeDef *) MPS2_SSP1_BASE )
|
||||
#define MPS2_SSP2 ((MPS2_SSP_TypeDef *) MPS2_SSP2_BASE )
|
||||
#define MPS2_SSP3 ((MPS2_SSP_TypeDef *) MPS2_SSP3_BASE )
|
||||
#define MPS2_SSP4 ((MPS2_SSP_TypeDef *) MPS2_SSP4_BASE )
|
||||
|
||||
/******************************************************************************/
|
||||
/* General Function Definitions */
|
||||
|
|
|
@ -1,265 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "cmsis.h"
|
||||
#include "apb_timer.h"
|
||||
|
||||
/* Timer Private Data */
|
||||
typedef struct {
|
||||
/* Timer Definition */
|
||||
CMSDK_TIMER_TypeDef *timerN;
|
||||
/* Timer IRQn */
|
||||
uint32_t timerIRQn;
|
||||
/* Timer Reload Value */
|
||||
uint32_t timerReload;
|
||||
/* Timer state */
|
||||
uint32_t state;
|
||||
} apb_timer_t;
|
||||
|
||||
/* Timer state definitions */
|
||||
#define TIMER_INITIALIZED (1)
|
||||
#define TIMER_ENABLED (1 << 1)
|
||||
|
||||
/*
|
||||
* This Timer is written for MBED OS and keeps count
|
||||
* of the ticks. All the elaboration logic is demanded
|
||||
* to the upper layers.
|
||||
*/
|
||||
#define TIMER_MAX_VALUE 0xFFFFFFFF
|
||||
#define TIMER_TICKS_US (SystemCoreClock/1000000)
|
||||
|
||||
/* Timers Array */
|
||||
static apb_timer_t Timers[NUM_TIMERS];
|
||||
|
||||
void Timer_Index_Init(uint32_t timer, uint32_t reload,
|
||||
CMSDK_TIMER_TypeDef *TimerN, uint32_t IRQn)
|
||||
{
|
||||
Timers[timer].timerN = TimerN;
|
||||
Timers[timer].timerIRQn = IRQn;
|
||||
Timers[timer].timerReload = reload;
|
||||
Timers[timer].state = TIMER_INITIALIZED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Initialize(): Initializes an hardware timer
|
||||
* timer: timer to be Initialized
|
||||
* time_us: timer reload value in us - 0 to reload to timer max value
|
||||
* time_us = tick_value / TIMER_TICKS_US
|
||||
*/
|
||||
#define TIMER_INIT(index, reload) Timer_Index_Init(index, reload, CMSDK_TIMER##index, TIMER##index##_IRQn)
|
||||
void Timer_Initialize(uint32_t timer, uint32_t time_us)
|
||||
{
|
||||
uint32_t reload = 0;
|
||||
|
||||
if (timer < NUM_TIMERS) {
|
||||
if (time_us == 0) {
|
||||
reload = TIMER_MAX_VALUE;
|
||||
} else {
|
||||
reload = (time_us) * TIMER_TICKS_US;
|
||||
}
|
||||
switch (timer) {
|
||||
case 0:
|
||||
TIMER_INIT(0, reload);
|
||||
break;
|
||||
case 1:
|
||||
TIMER_INIT(1, reload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Enable(): Enables a hardware timer
|
||||
* timer: timer to be enabled
|
||||
*/
|
||||
void Timer_Enable(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized */
|
||||
if (Timers[timer].state == TIMER_INITIALIZED) {
|
||||
/* Disable Timer */
|
||||
(Timers[timer].timerN)->CTRL = 0x0;
|
||||
/* Reload Value */
|
||||
(Timers[timer].timerN)->RELOAD = Timers[timer].timerReload;
|
||||
/* Enable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk;
|
||||
/* Enable Counter */
|
||||
(Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
/* Change timer state */
|
||||
Timers[timer].state |= TIMER_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Disable(): Disables a hardware timer
|
||||
* timer: timer to be disabled
|
||||
*/
|
||||
void Timer_Disable(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized and enabled */
|
||||
if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) {
|
||||
/* Disable Timer */
|
||||
(Timers[timer].timerN)->CTRL = 0x0;
|
||||
/* Change timer state */
|
||||
Timers[timer].state = TIMER_INITIALIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_isEnabled(): verifies if a timer is enabled
|
||||
* timer: timer to be verified
|
||||
* @return: 0 disabled - 1 enabled
|
||||
*/
|
||||
uint32_t Timer_isEnabled(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized and enabled */
|
||||
if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Read(): provides timer VALUE
|
||||
* timer: timer to be read
|
||||
* @return: timer VALUE us
|
||||
*/
|
||||
uint32_t Timer_Read(uint32_t timer)
|
||||
{
|
||||
uint32_t return_value = 0;
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return_value = (Timers[timer].timerReload
|
||||
- (Timers[timer].timerN)->VALUE) / TIMER_TICKS_US;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_SetInterrupt(): sets timer Interrupt
|
||||
* timer: timer on which interrupt is set
|
||||
* time_us: reloading time in us
|
||||
*/
|
||||
void Timer_SetInterrupt(uint32_t timer, uint32_t time_us)
|
||||
{
|
||||
uint32_t load_time_us = 0;
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Disable Timer */
|
||||
Timer_Disable(timer);
|
||||
/* Enable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk;
|
||||
|
||||
/* Check time us condition */
|
||||
if (time_us == TIMER_DEFAULT_RELOAD) {
|
||||
load_time_us = TIMER_MAX_VALUE;
|
||||
} else {
|
||||
load_time_us = time_us * TIMER_TICKS_US;
|
||||
}
|
||||
|
||||
/* Initialize Timer Value */
|
||||
Timers[timer].timerReload = load_time_us;
|
||||
(Timers[timer].timerN)->RELOAD = Timers[timer].timerReload;
|
||||
(Timers[timer].timerN)->VALUE = Timers[timer].timerReload;
|
||||
/* Enable Counter */
|
||||
(Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
/* Change timer state */
|
||||
Timers[timer].state |= TIMER_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_DisableInterrupt(): disables timer interrupt
|
||||
* timer: timer on which interrupt is disabled
|
||||
*/
|
||||
void Timer_DisableInterrupt(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Disable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL &= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_ClearInterrupt(): clear timer interrupt
|
||||
* timer: timer on which interrupt needs to be cleared
|
||||
*/
|
||||
void Timer_ClearInterrupt(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Clear Interrupt */
|
||||
(Timers[timer].timerN)->INTCLEAR = CMSDK_TIMER_INTCLEAR_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetIRQn(): returns IRQn of a Timer
|
||||
* timer: timer on which IRQn is defined - 0 if it is not defined
|
||||
*/
|
||||
uint32_t Timer_GetIRQn(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return Timers[timer].timerIRQn;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetTicksUS(): returns the number of Ticks per us
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: Ticks per us - 0 if the timer is disables
|
||||
*/
|
||||
uint32_t Timer_GetTicksUS(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return TIMER_TICKS_US;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetReloadValue(): returns the load value of the selected
|
||||
* timer.
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: reload value of the selected singletimer
|
||||
*/
|
||||
uint32_t Timer_GetReloadValue(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
if (timer == TIMER1) {
|
||||
return Timers[timer].timerReload / TIMER_TICKS_US;
|
||||
} else {
|
||||
return Timers[timer].timerReload / TIMER_TICKS_US;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This file is derivative of apb_timer.h from BEETLE */
|
||||
|
||||
#ifndef _APB_TIMER_DRV_H
|
||||
#define _APB_TIMER_DRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Supported Number of Timers */
|
||||
#define NUM_TIMERS 2
|
||||
#define TIMER0 0
|
||||
#define TIMER1 1
|
||||
|
||||
/* Default reload */
|
||||
#define TIMER_DEFAULT_RELOAD 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* Timer_Initialize(): Initializes an hardware timer
|
||||
* timer: timer to be Initialized
|
||||
* time_us: timer reload value in us - 0 to reload to timer max value
|
||||
* time_us = tick_value / TIMER_TICK_US
|
||||
*/
|
||||
void Timer_Initialize(uint32_t timer, uint32_t time_us);
|
||||
|
||||
/*
|
||||
* Timer_Enable(): Enables an hardware timer
|
||||
* timer: timer to be enabled
|
||||
*/
|
||||
void Timer_Enable(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_Disable(): Disables an hardware timer
|
||||
* timer: timer to be disabled
|
||||
*/
|
||||
void Timer_Disable(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_isEnabled(): verifies if a timer is enabled
|
||||
* timer: timer to be verified
|
||||
* @return: 0 disabled - 1 enabled
|
||||
*/
|
||||
uint32_t Timer_isEnabled(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_Read(): provides timer VALUE
|
||||
* timer: timer to be read
|
||||
* @return: timer VALUE
|
||||
*/
|
||||
uint32_t Timer_Read(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_SetInterrupt(): sets timer Interrupt
|
||||
* timer: timer on which interrupt is set
|
||||
* time_us: reloading time in us
|
||||
*/
|
||||
void Timer_SetInterrupt(uint32_t timer, uint32_t time_us);
|
||||
|
||||
/*
|
||||
* Timer_DisableInterrupt(): disables timer interrupt
|
||||
* timer: timer on which interrupt is disabled
|
||||
*/
|
||||
void Timer_DisableInterrupt(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_ClearInterrupt(): clear timer interrupt
|
||||
* timer: timer on which interrupt needs to be cleared
|
||||
*/
|
||||
void Timer_ClearInterrupt(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetIRQn(): returns IRQn of a Timer
|
||||
* timer: timer on which IRQn is defined - 0 if it is not defined
|
||||
*/
|
||||
uint32_t Timer_GetIRQn(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetTicksUS(): returns the number of Ticks per us
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: Ticks per us - 0 if the timer is disables
|
||||
*/
|
||||
uint32_t Timer_GetTicksUS(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetReloadValue(): returns the load value of the selected
|
||||
* timer.
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: reload value of the selected singletimer
|
||||
*/
|
||||
uint32_t Timer_GetReloadValue(uint32_t timer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _APB_TIMER_DRV_H */
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015-2017 ARM Limited
|
||||
* Copyright (c) 2015-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,7 +25,5 @@
|
|||
#include "SMM_MPS2.h"
|
||||
/* NVIC Driver */
|
||||
#include "cmsis_nvic.h"
|
||||
/* APB Timer */
|
||||
#include "apb_timer.h"
|
||||
|
||||
#endif /* MBED_CMSIS_H */
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_LTD_DEVICE_CFG_H__
|
||||
#define __ARM_LTD_DEVICE_CFG_H__
|
||||
|
||||
/**
|
||||
* \file device_cfg.h
|
||||
* \brief
|
||||
* This is the default device configuration file with all peripherals
|
||||
* defined and configured to be used via the non-secure base address.
|
||||
* This file is an example of how to define your own configuration file
|
||||
* with the peripherals required for your application.
|
||||
*/
|
||||
|
||||
/* CMSDK Timers */
|
||||
#define ARM_CMSDK_TIMER0
|
||||
#define ARM_CMSDK_TIMER1
|
||||
|
||||
/* ARM GPIO */
|
||||
#define ARM_GPIO0
|
||||
#define ARM_GPIO1
|
||||
#define ARM_GPIO2
|
||||
#define ARM_GPIO3
|
||||
|
||||
/* ARM MPS2 IO FPGAIO */
|
||||
#define ARM_MPS2_IO_FPGAIO
|
||||
|
||||
/* ARM MPS2 IO SCC */
|
||||
#define ARM_MPS2_IO_SCC
|
||||
|
||||
/* ARM SPI PL022 */
|
||||
#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */
|
||||
#define ARM_SPI0
|
||||
#define ARM_SPI1
|
||||
#define ARM_SPI2
|
||||
#define ARM_SPI3
|
||||
#define ARM_SPI4
|
||||
|
||||
/* ARM UART */
|
||||
#define DEFAULT_UART_BAUDRATE 9600
|
||||
#define ARM_UART0
|
||||
#define ARM_UART1
|
||||
#define ARM_UART2
|
||||
#define ARM_UART3
|
||||
#define ARM_UART4
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_gpio_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* GPIO state definitions */
|
||||
#define ARM_GPIO_INITIALIZED (1 << 0)
|
||||
|
||||
#define MAX_PIN_NBR 16
|
||||
|
||||
/* GPIO register map structure */
|
||||
struct arm_gpio_reg_map_t {
|
||||
volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */
|
||||
volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output
|
||||
* latch register */
|
||||
volatile uint32_t reserved0[2];
|
||||
volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable
|
||||
* set register */
|
||||
volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable
|
||||
* clear register */
|
||||
volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function
|
||||
* set register */
|
||||
volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function
|
||||
* clear register */
|
||||
volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable
|
||||
* set register */
|
||||
volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable
|
||||
* clear register */
|
||||
volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type
|
||||
* set register */
|
||||
volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type
|
||||
* clear register */
|
||||
volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity
|
||||
* set register */
|
||||
volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity
|
||||
* clear register */
|
||||
union {
|
||||
volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status
|
||||
* register */
|
||||
volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear
|
||||
* register */
|
||||
}intreg;
|
||||
volatile uint32_t reserved1[241];
|
||||
volatile uint32_t lb_masked[256]; /* Offset: 0x400 - 0x7FC (R/W)
|
||||
* Lower byte masked access register */
|
||||
volatile uint32_t ub_masked[256]; /* Offset: 0x800 - 0xBFC (R/W)
|
||||
* Upper byte masked access register */
|
||||
};
|
||||
|
||||
/*
|
||||
* \brief Configures the pin or port.
|
||||
*
|
||||
* \param[in] p_gpio_port GPIO port to configure \ref ahbarm_gpio_reg_map_t
|
||||
* \param[in] mask Pin bit mask.
|
||||
* \param[in] flags Pin flags.
|
||||
*/
|
||||
static void set_port_config(struct arm_gpio_reg_map_t* p_gpio_port,
|
||||
uint32_t mask,
|
||||
uint32_t flags)
|
||||
{
|
||||
if(flags & ARM_GPIO_PIN_DISABLE) {
|
||||
p_gpio_port->altfuncset = mask;
|
||||
return;
|
||||
}
|
||||
|
||||
if(flags & ARM_GPIO_OUTPUT) {
|
||||
p_gpio_port->outenableset = mask;
|
||||
} else if(flags & ARM_GPIO_INPUT) {
|
||||
p_gpio_port->outenableclr = mask;
|
||||
}
|
||||
|
||||
/* Sets interrupt configuration */
|
||||
if(flags & ARM_GPIO_IRQ) {
|
||||
/* Interrupt type: EDGE = 1 - LEVEL = 0 */
|
||||
if(flags & ARM_GPIO_IRQ_EDGE) {
|
||||
p_gpio_port->inttypeset = mask;
|
||||
} else if(flags & ARM_GPIO_IRQ_LEVEL) {
|
||||
p_gpio_port->inttypeclr = mask;
|
||||
}
|
||||
|
||||
/* Interrupt polarity */
|
||||
if(flags & ARM_GPIO_IRQ_ACTIVE_LOW) {
|
||||
p_gpio_port->intpolclr = mask;
|
||||
} else if(flags & ARM_GPIO_IRQ_ACTIVE_HIGH) {
|
||||
p_gpio_port->intpolset = mask;
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & ARM_GPIO_PIN_ENABLE) {
|
||||
p_gpio_port->altfuncclr = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gpio_init(struct arm_gpio_dev_t* dev)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
/* Disables all pins in this port */
|
||||
set_port_config(p_gpio_port, DEFAULT_PORT_MASK, ARM_GPIO_PIN_DISABLE);
|
||||
|
||||
dev->data->port_mask = DEFAULT_PORT_MASK;
|
||||
dev->data->state = ARM_GPIO_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint32_t pin_mask;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
pin_mask = (1UL << pin_num);
|
||||
set_port_config(p_gpio_port, pin_mask, flags);
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
set_port_config(p_gpio_port, dev->data->port_mask, flags);
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* As ARM is a read-modify-write architecture, before set a
|
||||
* value on a GPIO register it is required to disable the
|
||||
* interrupts to prevent problems in a multitasking
|
||||
* environment */
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
if(value) {
|
||||
/* Sets the pin */
|
||||
p_gpio_port->dataout |= (1UL << pin_num);
|
||||
} else {
|
||||
/* Clears the pin */
|
||||
p_gpio_port->dataout &= ~(1UL << pin_num);
|
||||
}
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
if(value) {
|
||||
/* Sets masked pins */
|
||||
p_gpio_port->dataout |= dev->data->port_mask;
|
||||
} else {
|
||||
/* Clears masked pins */
|
||||
p_gpio_port->dataout &= ~(dev->data->port_mask);
|
||||
}
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch. */
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
uint32_t value;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
value = p_gpio_port->data;
|
||||
|
||||
if(access == ARM_GPIO_ACCESS_PIN) {
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return -1;
|
||||
}
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
} else {
|
||||
value &= dev->data->port_mask;
|
||||
}
|
||||
|
||||
return (int32_t)value;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
enum arm_gpio_irq_status_t status)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
mask = dev->data->port_mask;
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
if(status == ARM_GPIO_IRQ_ENABLE) {
|
||||
p_gpio_port->intenset = mask;
|
||||
} else {
|
||||
p_gpio_port->intenclr = mask;
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t* status)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*status = p_gpio_port->intreg.intstatus;
|
||||
|
||||
if(access == ARM_GPIO_ACCESS_PIN) {
|
||||
*status = ((*status >> pin_num) & 1UL);
|
||||
} else {
|
||||
*status &= dev->data->port_mask;
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
p_gpio_port->intreg.intstatus = (1UL << pin_num);
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask)
|
||||
{
|
||||
dev->data->port_mask = (port_mask & DEFAULT_PORT_MASK);
|
||||
}
|
||||
|
||||
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev)
|
||||
{
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (dev->data->port_mask & DEFAULT_PORT_MASK);
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_gpio_drv.h
|
||||
* \brief Generic driver for ARM GPIO.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_GPIO_DRV_H__
|
||||
#define __ARM_GPIO_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PORT_MASK 0xFFFF /* Default port mask */
|
||||
|
||||
/* GPIO flags */
|
||||
#define ARM_GPIO_PIN_DISABLE (1 << 0)
|
||||
#define ARM_GPIO_PIN_ENABLE (1 << 1)
|
||||
#define ARM_GPIO_OUTPUT (1 << 2)
|
||||
#define ARM_GPIO_INPUT (1 << 3)
|
||||
#define ARM_GPIO_IRQ (1 << 4)
|
||||
#define ARM_GPIO_IRQ_EDGE (1 << 5)
|
||||
#define ARM_GPIO_IRQ_LEVEL (1 << 6)
|
||||
#define ARM_GPIO_IRQ_ACTIVE_LOW (1 << 7)
|
||||
#define ARM_GPIO_IRQ_ACTIVE_HIGH (1 << 8)
|
||||
|
||||
/* ARM GPIO enumeration types */
|
||||
enum arm_gpio_access_t {
|
||||
ARM_GPIO_ACCESS_PIN = 0, /*!< Pin access to GPIO */
|
||||
ARM_GPIO_ACCESS_PORT /*!< Port access to GPIO */
|
||||
};
|
||||
|
||||
enum arm_gpio_irq_status_t {
|
||||
ARM_GPIO_IRQ_DISABLE = 0, /*!< Disable interruptions */
|
||||
ARM_GPIO_IRQ_ENABLE /*!< Enable interruptions */
|
||||
};
|
||||
|
||||
enum arm_gpio_error_t {
|
||||
ARM_GPIO_ERR_NONE = 0, /*!< No error */
|
||||
ARM_GPIO_ERR_INVALID_ARG, /*!< Error invalid input argument */
|
||||
ARM_GPIO_ERR_PORT_NOT_INIT /*!< Error GPIO port not initialized */
|
||||
};
|
||||
|
||||
/* ARM GPIO device configuration structure */
|
||||
struct arm_gpio_dev_cfg_t {
|
||||
const uint32_t base; /*!< GPIO base address */
|
||||
};
|
||||
|
||||
/* ARM GPIO device data structure */
|
||||
struct arm_gpio_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the gpio driver
|
||||
is initialized and enabled */
|
||||
uint32_t port_mask; /*!< Port mask used for any port access */
|
||||
};
|
||||
|
||||
/* ARM GPIO device structure */
|
||||
struct arm_gpio_dev_t {
|
||||
const struct arm_gpio_dev_cfg_t* const cfg; /*!< GPIO configuration */
|
||||
struct arm_gpio_dev_data_t* const data; /*!< GPIO data */
|
||||
};
|
||||
|
||||
/* ARM GPIO pin structure */
|
||||
struct arm_gpio_pin_t {
|
||||
uint32_t number; /*!< Pin number */
|
||||
enum arm_gpio_access_t access_type; /*!< Type of access in the
|
||||
GPIO block */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes GPIO port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_gpio_init(struct arm_gpio_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Configurates pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] flags Pin flags \ref arm_gpio_flags_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* \brief Writes to output pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value(s) to set.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
* \note As ARM is a read-modify-write architecture, before writing a
|
||||
* value on a GPIO pin it is required to disable the
|
||||
* interrupts to prevent problems in a multitasking
|
||||
* environment.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief Reads the pin or port status.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value of input pin(s).
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
* Negative value for error.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt status for the given pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] status Interrupt status \ref arm_gpio_irq_status
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
enum arm_gpio_irq_status_t status);
|
||||
|
||||
/**
|
||||
* \brief Gets interrupt status for the given pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[out] status Interrupt status values. If the access is by pin, then
|
||||
* the status will be 0 or 1.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t* status);
|
||||
|
||||
/**
|
||||
* \brief Clears gpio interrupt.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Sets gpio mask for port access.
|
||||
*
|
||||
* \param[in] dev GPIO port \ref arm_gpio_dev_t
|
||||
* \param[in] port_mask New port mask to set, only the 16 LSb are taken into
|
||||
* account
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask);
|
||||
|
||||
/**
|
||||
* \brief Gets gpio mask for port access.
|
||||
*
|
||||
* \param[in] dev GPIO port \ref arm_gpio_dev_t
|
||||
*
|
||||
* \return Returns the current port mask
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ARM_GPIO_DRV_H__ */
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_mps2_io_drv.h"
|
||||
|
||||
/* There is at most 8 LEDs and switches on MPS2 SCC and 2 on FPGA IO */
|
||||
#define MAX_PIN_NBR_SCC 8
|
||||
#define MAX_PIN_NBR_FPGAIO 2
|
||||
|
||||
/* Mask to 1 the first X bits */
|
||||
#define MASK(X) ((1 << (X)) - 1)
|
||||
|
||||
/* MPS2 IO register map structure */
|
||||
struct arm_mps2_io_reg_map_t {
|
||||
union {
|
||||
volatile uint32_t scc_leds; /* Offset: 0x000 (R/W) Controls the MCC
|
||||
* user LEDs
|
||||
* [31:8] : Reserved
|
||||
* [7:0] : MCC LEDs */
|
||||
volatile uint32_t fpgaio_leds; /* Offset: 0x000 (R/W) LED connections
|
||||
* [31:2] : Reserved
|
||||
* [1:0] : FPGAIO LEDs */
|
||||
} led_reg;
|
||||
volatile uint32_t reserved[1];
|
||||
union {
|
||||
volatile uint32_t scc_switches; /* Offset: 0x008 (R/ ) Denotes the
|
||||
* state of the MCC
|
||||
* user switches
|
||||
* [31:8] : Reserved
|
||||
* [7:0] : State of the MCC
|
||||
* switches */
|
||||
volatile uint32_t fpgaio_buttons;/* Offset: 0x008 (R/ ) Buttons
|
||||
* [31:2] : Reserved
|
||||
* [1:0] : Buttons */
|
||||
} button_reg;
|
||||
};
|
||||
|
||||
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
/* Mask of involved bits */
|
||||
uint32_t write_mask = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (access) {
|
||||
case ARM_MPS2_IO_ACCESS_PIN:
|
||||
write_mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_MPS2_IO_ACCESS_PORT:
|
||||
write_mask = MASK(MAX_PIN_NBR_SCC);
|
||||
break;
|
||||
/*
|
||||
* default: explicitely not used to force to cover all enumeration
|
||||
* cases
|
||||
*/
|
||||
}
|
||||
|
||||
if (value) {
|
||||
p_mps2_io_port->led_reg.scc_leds |= write_mask;
|
||||
} else {
|
||||
p_mps2_io_port->led_reg.scc_leds &= ~write_mask;
|
||||
}
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (access) {
|
||||
case ARM_MPS2_IO_ACCESS_PIN:
|
||||
write_mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_MPS2_IO_ACCESS_PORT:
|
||||
write_mask = MASK(MAX_PIN_NBR_FPGAIO);
|
||||
break;
|
||||
/*
|
||||
* default: explicitely not used to force to cover all enumeration
|
||||
* cases
|
||||
*/
|
||||
}
|
||||
|
||||
if (value) {
|
||||
p_mps2_io_port->led_reg.fpgaio_leds |= write_mask;
|
||||
} else {
|
||||
p_mps2_io_port->led_reg.fpgaio_leds &= ~write_mask;
|
||||
}
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
uint32_t value = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->button_reg.scc_switches & MASK(MAX_PIN_NBR_SCC);
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->button_reg.fpgaio_buttons &
|
||||
MASK(MAX_PIN_NBR_FPGAIO);
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
if (access == ARM_MPS2_IO_ACCESS_PIN) {
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
uint32_t value = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->led_reg.scc_leds & MASK(MAX_PIN_NBR_SCC);
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->led_reg.fpgaio_leds & MASK(MAX_PIN_NBR_FPGAIO);
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
if (access == ARM_MPS2_IO_ACCESS_PIN) {
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_mps2_io_drv.h
|
||||
* \brief Generic driver for ARM MPS2 IO.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_MPS2_IO_DRV_H__
|
||||
#define __ARM_MPS2_IO_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO enumeration types */
|
||||
enum arm_mps2_io_access_t {
|
||||
ARM_MPS2_IO_ACCESS_PIN = 0, /*!< Pin access to MPS2 IO */
|
||||
ARM_MPS2_IO_ACCESS_PORT /*!< Port access to MPS2 IO */
|
||||
};
|
||||
|
||||
enum arm_mps2_io_type_t {
|
||||
ARM_MPS2_IO_TYPE_SCC = 0, /*!< Use the SCC IO device */
|
||||
ARM_MPS2_IO_TYPE_FPGAIO /*!< Use the FPGA IO device */
|
||||
};
|
||||
|
||||
/* ARM MPS2 IO device configuration structure */
|
||||
struct arm_mps2_io_dev_cfg_t {
|
||||
const uint32_t base; /*!< MPS2 IO base address */
|
||||
const enum arm_mps2_io_type_t type; /*!< SCC or FPGAIO */
|
||||
};
|
||||
|
||||
/* ARM MPS2 IO device structure */
|
||||
struct arm_mps2_io_dev_t {
|
||||
const struct arm_mps2_io_dev_cfg_t* const cfg; /*!< MPS2 IO configuration */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Writes to output LEDs.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to write \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value(s) to set.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief Reads the buttons status.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Reads the LED status.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_MPS2_IO_DRV_H__ */
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* UART register map structure */
|
||||
struct _arm_uart_reg_map_t {
|
||||
volatile uint32_t data; /* Offset: 0x000 (R/W) data register */
|
||||
volatile uint32_t state; /* Offset: 0x004 (R/W) status register */
|
||||
volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */
|
||||
union {
|
||||
volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status
|
||||
* register */
|
||||
volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear
|
||||
* register */
|
||||
}intr_reg;
|
||||
volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider
|
||||
* register */
|
||||
};
|
||||
|
||||
/* CTRL Register */
|
||||
#define ARM_UART_TX_EN (1ul << 0)
|
||||
#define ARM_UART_RX_EN (1ul << 1)
|
||||
#define ARM_UART_TX_INTR_EN (1ul << 2)
|
||||
#define ARM_UART_RX_INTR_EN (1ul << 3)
|
||||
|
||||
/* STATE Register */
|
||||
#define ARM_UART_TX_BF (1ul << 0)
|
||||
#define ARM_UART_RX_BF (1ul << 1)
|
||||
|
||||
/* INTSTATUS Register */
|
||||
#define ARM_UART_TX_INTR (1ul << 0)
|
||||
#define ARM_UART_RX_INTR (1ul << 1)
|
||||
|
||||
/* UART state definitions */
|
||||
#define ARM_UART_INITIALIZED (1ul << 0)
|
||||
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Sets baudrate and system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
dev->data->baudrate = dev->cfg->default_baudrate;
|
||||
|
||||
/* Sets baudrate */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
|
||||
|
||||
dev->data->state = ARM_UART_INITIALIZED;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate)
|
||||
{
|
||||
uint32_t bauddiv;
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(baudrate == 0) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets baudrate */
|
||||
bauddiv = (dev->data->system_clk / baudrate);
|
||||
dev->data->baudrate = baudrate;
|
||||
|
||||
/* Minimum bauddiv value */
|
||||
if(bauddiv < 16) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
p_uart->bauddiv = bauddiv;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
return dev->data->baudrate;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
|
||||
/* Updates baudrate divider */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(p_uart->state & ARM_UART_RX_BF)) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Reads data */
|
||||
*byte = (uint8_t)p_uart->data;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(p_uart->state & ARM_UART_TX_BF) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Sends data */
|
||||
p_uart->data = byte;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_TX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED ) {
|
||||
p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !(p_uart->state & ARM_UART_TX_BF);
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_RX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (p_uart->state & ARM_UART_RX_BF);
|
||||
}
|
||||
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
/* Clears pending interrupts */
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
switch(p_uart->intr_reg.intrstatus) {
|
||||
case ARM_UART_TX_INTR:
|
||||
return ARM_UART_IRQ_TX;
|
||||
break;
|
||||
case ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_RX;
|
||||
break;
|
||||
case ARM_UART_TX_INTR | ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_COMBINED;
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
return ARM_UART_IRQ_NONE;
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_uart_drv.h
|
||||
* \brief Generic driver for ARM UART.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_UART_DRV_H__
|
||||
#define __ARM_UART_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ARM UART device configuration structure */
|
||||
struct arm_uart_dev_cfg_t {
|
||||
const uint32_t base; /*!< UART base address */
|
||||
const uint32_t default_baudrate; /*!< Default baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device data structure */
|
||||
struct arm_uart_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the uart driver
|
||||
is initialized and enabled */
|
||||
uint32_t system_clk; /*!< System clock */
|
||||
uint32_t baudrate; /*!< Baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device structure */
|
||||
struct arm_uart_dev_t {
|
||||
const struct arm_uart_dev_cfg_t* const cfg; /*!< UART configuration */
|
||||
struct arm_uart_dev_data_t* const data; /*!< UART data */
|
||||
};
|
||||
|
||||
/* ARM UART enumeration types */
|
||||
enum arm_uart_error_t {
|
||||
ARM_UART_ERR_NONE = 0, /*!< No error */
|
||||
ARM_UART_ERR_INVALID_ARG, /*!< Error invalid input argument */
|
||||
ARM_UART_ERR_INVALID_BAUD, /*!< Invalid baudrate */
|
||||
ARM_UART_ERR_NOT_INIT, /*!< Error UART not initialized */
|
||||
ARM_UART_ERR_NOT_READY, /*!< Error UART not ready */
|
||||
};
|
||||
|
||||
enum arm_uart_irq_t {
|
||||
ARM_UART_IRQ_RX, /*!< RX interrupt source */
|
||||
ARM_UART_IRQ_TX, /*!< TX interrupt source */
|
||||
ARM_UART_IRQ_COMBINED, /*!< RX-TX combined interrupt source */
|
||||
ARM_UART_IRQ_NONE = 0xFF /*!< RX-TX combined interrupt source */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes UART. It uses the default baudrate to configure
|
||||
* the peripheral at this point.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] baudrate New baudrate.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* \brief Gets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns the UART baudrate.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
/**
|
||||
* \brief Reads one byte from UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Pointer to byte.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev and byte
|
||||
* pointer are NULL, and if the driver is initialized.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte);
|
||||
|
||||
/**
|
||||
* \brief Writes a byte to UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Byte to write.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to have better performance.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte);
|
||||
|
||||
/**
|
||||
* \brief Enables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Tx is ready to send more data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if TX is ready, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables RX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables RX interrupt
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Rx has data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if RX has data, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears UART interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] irq IRQ source to clean \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq);
|
||||
|
||||
/**
|
||||
* \brief Returns UART interrupt status.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return IRQ status \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ARM_UART_DRV_H__ */
|
|
@ -0,0 +1,870 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "spi_pl022_drv.h"
|
||||
|
||||
/******************************************************************************
|
||||
* PL022 device specific definitions based on DDI0194H_ssp_pl022_trm.pdf which
|
||||
* is available from infocenter.arm.com.
|
||||
*
|
||||
* This version of driver aims at necessary functionality for MPS2 board only
|
||||
*****************************************************************************/
|
||||
|
||||
/* Structure for the SSP Primary Cell device registers */
|
||||
struct spi_pl022_dev_reg_map_t {
|
||||
volatile uint32_t sspcr0; /* Control register 0 */
|
||||
volatile uint32_t sspcr1; /* Control register 1 */
|
||||
volatile uint32_t sspdr; /* Data register */
|
||||
volatile uint32_t sspsr; /* Status register */
|
||||
volatile uint32_t sspcpsr; /* Clock prescale register */
|
||||
volatile uint32_t sspimsc; /* Interrupt mask set or clear register */
|
||||
volatile uint32_t sspris; /* Raw interrupt status register */
|
||||
volatile uint32_t sspmis; /* Masked interrupt status register */
|
||||
volatile uint32_t sspicr; /* Interrupt clear register */
|
||||
volatile uint32_t sspdmacr; /* DMA control register */
|
||||
volatile uint32_t reserved[1006];/* Reserved from Base+0x28-0xFE0 */
|
||||
volatile uint32_t sspperiphid0; /* Peripheral id register 0 */
|
||||
volatile uint32_t sspperiphid1; /* Peripheral id register 1 */
|
||||
volatile uint32_t sspperiphid2; /* Peripheral id register 2 */
|
||||
volatile uint32_t sspperiphid3; /* Peripheral id register 3 */
|
||||
volatile uint32_t ssppcellid0; /* Primary cell id register 0 */
|
||||
volatile uint32_t ssppcellid1; /* Primary cell id register 1 */
|
||||
volatile uint32_t ssppcellid2; /* Primary cell id register 2 */
|
||||
volatile uint32_t ssppcellid3; /* Primary cell id register 3 */
|
||||
};
|
||||
|
||||
/*--- SSP Control Register 0 ---*/
|
||||
|
||||
/* Data Size Select {0x3=4 ... 0xF=16} */
|
||||
#define SPI_PL022_SSPCR0_DSS_POS 0
|
||||
#define SPI_PL022_SSPCR0_DSS_MSK 0xF
|
||||
|
||||
/* Frame format */
|
||||
#define SPI_PL022_SSPCR0_FRF_POS 4
|
||||
#define SPI_PL022_SSPCR0_FRF_MSK (0x3ul<<SPI_PL022_SSPCR0_FRF_POS)
|
||||
#define SPI_PL022_SSPCR0_FRF_MOT_SPI 0x0
|
||||
#define SPI_PL022_SSPCR0_FRF_TI_SS 0x1
|
||||
#define SPI_PL022_SSPCR0_FRF_MICROWIRE 0x2
|
||||
#define SPI_PL022_SSPCR0_FRF_RES 0x3
|
||||
|
||||
/* Clock polarity applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPO_POS 6
|
||||
#define SPI_PL022_SSPCR0_SPO_MSK (0x1ul<<SPI_PL022_SSPCR0_SPO_POS)
|
||||
|
||||
/* Clock phase applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPH_POS 7
|
||||
#define SPI_PL022_SSPCR0_SPH_MSK (0x1ul<<SPI_PL022_SSPCR0_SPH_POS)
|
||||
|
||||
/* Serial clock rate */
|
||||
#define SPI_PL022_SSPCR0_SCR_POS 8
|
||||
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
/*--- SSP Control Register 1 ---*/
|
||||
|
||||
/* Loopback mode*/
|
||||
#define SPI_PL022_SSPCR1_LBM_POS 0
|
||||
#define SPI_PL022_SSPCR1_LBM_MSK (0x1ul<<SPI_PL022_SSPCR1_LBM_POS)
|
||||
|
||||
/* Syncrhonous serial port enable*/
|
||||
#define SPI_PL022_SSPCR1_SSE_POS 1
|
||||
#define SPI_PL022_SSPCR1_SSE_MSK (0x1ul<<SPI_PL022_SSPCR1_SSE_POS)
|
||||
|
||||
/* Master or Slave select */
|
||||
#define SPI_PL022_SSPCR1_MS_POS 2
|
||||
#define SPI_PL022_SSPCR1_MS_MSK (0x1ul<<SPI_PL022_SSPCR1_MS_POS)
|
||||
|
||||
/* Slave mode output disable */
|
||||
#define SPI_PL022_SSPCR1_SOD_POS 3
|
||||
#define SPI_PL022_SSPCR1_SOD_MSK (0x1ul<<SPI_PL022_SSPCR1_SOD_POS)
|
||||
|
||||
/*--- Clock PreScale Register ---*/
|
||||
|
||||
/* Divisor */
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_POS 0
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_MSK (0xFFul<<SPI_PL022_SSPCPSR_CPSDVSR_POS)
|
||||
#define SPI_PL022_INVALID_SSPCPSR_VALUE 0
|
||||
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
|
||||
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
|
||||
#define SPI_PL022_MAX_SCR_VALUE 255
|
||||
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register --- */
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register ---*/
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
#define SPI_PL022_SSPIMSC_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPIMSC_TXIM_POS+1))-1)
|
||||
|
||||
/*--- Raw Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPRIS_RORRIS_POS 0
|
||||
#define SPI_PL022_SSPRIS_RORRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RORRIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPRIS_RTRIS_POS 1
|
||||
#define SPI_PL022_SSPRIS_RTRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RTRIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPRIS_RXRIS_POS 2
|
||||
#define SPI_PL022_SSPRIS_RXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RXRIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPRIS_TXRIS_POS 3
|
||||
#define SPI_PL022_SSPRIS_TXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_TXRIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPRIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPRIS_TXRIS_POS+1))-1)
|
||||
|
||||
/*--- Masked Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPMIS_RORMIS_POS 0
|
||||
#define SPI_PL022_SSPMIS_RORMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RORMIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPMIS_RTMIS_POS 1
|
||||
#define SPI_PL022_SSPMIS_RTMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RTMIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPMIS_RXMIS_POS 2
|
||||
#define SPI_PL022_SSPMIS_RXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RXMIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPMIS_TXMIS_POS 3
|
||||
#define SPI_PL022_SSPMIS_TXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_TXMIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPMIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPMIS_TXMIS_POS+1))-1)
|
||||
|
||||
/*--- Interrupt Clear Register --- */
|
||||
|
||||
/* SSPRORINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RORIC_POS 0
|
||||
#define SPI_PL022_SSPICR_RORIC_MSK (0x1ul<<SPI_PL022_SSPICR_RORIC_POS)
|
||||
|
||||
/* SSPRTINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RTIC_POS 1
|
||||
#define SPI_PL022_SSPICR_RTIC_MSK (0x1ul<<SPI_PL022_SSPICR_RTIC_POS)
|
||||
|
||||
#define SPI_PL022_SSPICR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPICR_RTIC_POS+1))-1)
|
||||
|
||||
/*--- DMA Control Register --- */
|
||||
|
||||
/* Receive DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_POS 0
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_RXDMAE_POS)
|
||||
|
||||
/* Transmit DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_POS 1
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_TXDMAE_POS)
|
||||
|
||||
#define SPI_PL022_SSPDMACR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPDMACR_TXDMAE_POS+1))-1)
|
||||
|
||||
/*--- Peripheral Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPERIPH_ID_OFFSET (0xFE0ul)
|
||||
|
||||
/* Part Number 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE 8
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS)
|
||||
|
||||
/* Part Number 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_SIZE 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS)
|
||||
|
||||
/* Designer 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS)
|
||||
|
||||
/* Designer 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS)
|
||||
|
||||
/* Revision */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_REVISION_POS)
|
||||
|
||||
/* Config */
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID3_CONFIG_POS)
|
||||
|
||||
/*--- PrimeCell Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID_OFFSET (0xFF0ul)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID0_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID0_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID0_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID1_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID1_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID1_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID2_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID2_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID2_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID3_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID3_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID3_POS)
|
||||
|
||||
/* ARM SPI PL022 state definitions */
|
||||
#define SPI_PL022_INITIALIZED (1 << 0)
|
||||
|
||||
#define WORD_1BYTE_MASK (0xFFul)
|
||||
#define WORD_2BYTES_MASK (0xFFFFul)
|
||||
|
||||
|
||||
/************************* PL022 TEST Definitions ******************************/
|
||||
#define SPI_PL022_TEST_REG_BASE (0x80ul)
|
||||
|
||||
struct spi_pl022_dev_test_reg_map_t {
|
||||
volatile uint32_t ssptcr; /* Test Control register */
|
||||
volatile uint32_t sspitip; /* Integration test input register */
|
||||
volatile uint32_t sspitop; /* Integration test output register */
|
||||
volatile uint32_t ssptdr; /* Test data register */
|
||||
};
|
||||
|
||||
/* Test control register */
|
||||
#define SPI_PL022_SSPTCR_ITEN_POS 0
|
||||
#define SPI_PL022_SSPTCR_ITEN_MSK (0x1ul<<SPI_PL022_SSPTCR_ITEN_POS)
|
||||
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_POS 1
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_MSK (0x1ul<<SPI_PL022_SSPTCR_TESTFIFO_POS)
|
||||
|
||||
|
||||
/* Integration test input register */
|
||||
#define SPI_PL022_SSPITIP_RXD_POS 0
|
||||
#define SPI_PL022_SSPITIP_RXD_MSK (0x1ul<<SPI_PL022_SSPITIP_RXD_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_FSSIN_POS 1
|
||||
#define SPI_PL022_SSPITIP_FSSIN_MSK (0x1ul<<SPI_PL022_SSPITIP_FSSIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_CLKIN_POS 2
|
||||
#define SPI_PL022_SSPITIP_CLKIN_MSK (0x1ul<<SPI_PL022_SSPITIP_CLKIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_POS 3
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_RXDMACLR_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_POS 4
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_TXDMACLR_POS)
|
||||
|
||||
/* Integration test output register */
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_POS 10
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_POS 11
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMASREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_POS 12
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_POS 13
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMASREQ_POS)
|
||||
|
||||
/************************* PL022 Definitions End ******************************/
|
||||
|
||||
|
||||
/*
|
||||
* \brief Calculates clock prescale divisor and sets serial clock rate
|
||||
* for the SPI PL022 device.
|
||||
*
|
||||
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
|
||||
* \param[in] sys_clk System clock.
|
||||
* \param[in/out] cr0 Pointer to PL022 control register 0
|
||||
* \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \return Value of the SSPCPSR register \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \note This function doesn't check if sys_clk or ctrl_cfg->bit_rate is 0
|
||||
*/
|
||||
static uint32_t spi_calc_clock_rate(
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
|
||||
uint32_t sys_clk, volatile uint32_t *cr0)
|
||||
{
|
||||
uint32_t clkps_dvsr; /* clock prescale divisor */
|
||||
uint32_t scr; /* serial clock rate */
|
||||
|
||||
for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE;
|
||||
clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) {
|
||||
|
||||
/* Calculate clock rate based on the new clock prescale divisor */
|
||||
scr = (sys_clk / (clkps_dvsr * ctrl_cfg->bit_rate)) - 1;
|
||||
|
||||
/* Checks if it can be supported by the divider */
|
||||
if (scr <= SPI_PL022_MAX_SCR_VALUE) {
|
||||
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
*cr0 |= (scr << SPI_PL022_SSPCR0_SCR_POS);
|
||||
return clkps_dvsr;
|
||||
}
|
||||
}
|
||||
|
||||
/* no good value was found */
|
||||
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
return SPI_PL022_INVALID_SSPCPSR_VALUE;
|
||||
}
|
||||
|
||||
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return p_spi->sspsr;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Configures the SPI PL022 device.
|
||||
*
|
||||
* \param[in] spi_dev Pointer to SPI memory map \ref spi_pl022_dev_reg_map_t
|
||||
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*/
|
||||
static enum spi_pl022_error_t spi_set_configuration(
|
||||
struct spi_pl022_dev_reg_map_t* spi_dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
uint32_t tmp_cr0, tmp_cr1;
|
||||
uint32_t clk_dvsr;
|
||||
|
||||
if(!sys_clk || !ctrl_cfg->bit_rate) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* Word size */
|
||||
tmp_cr0 = ((ctrl_cfg->word_size -1) << SPI_PL022_SSPCR0_DSS_POS)
|
||||
& SPI_PL022_SSPCR0_DSS_MSK;
|
||||
|
||||
/* Frame format is stored in the least 2 bits*/
|
||||
switch(ctrl_cfg->frame_format & 0x3ul)
|
||||
{
|
||||
case SPI_PL022_CFG_FRF_MOT:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MOT_SPI << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
/* Add motorola phase & polarity */
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_SPO_MSK & SPI_PL022_SSPCR0_SPH_MSK);
|
||||
break;
|
||||
case SPI_PL022_CFG_FRF_TI:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_TI_SS << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
break;
|
||||
case SPI_PL022_CFG_FRF_MICROWIRE:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MICROWIRE << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
break;
|
||||
default:
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
/* Clock logic */
|
||||
clk_dvsr = spi_calc_clock_rate(ctrl_cfg, sys_clk, &tmp_cr0);
|
||||
|
||||
if (SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
}
|
||||
|
||||
/* Enable device and set configured mode */
|
||||
tmp_cr1 = (0x1 << SPI_PL022_SSPCR1_SSE_POS) & SPI_PL022_SSPCR1_SSE_MSK;
|
||||
tmp_cr1 |= ((ctrl_cfg->spi_mode << SPI_PL022_SSPCR1_MS_POS)
|
||||
& SPI_PL022_SSPCR1_MS_MSK);
|
||||
|
||||
|
||||
/* Start initialization by disabling the device */
|
||||
spi_dev->sspcr1 = 0;
|
||||
|
||||
/* Set the value received for the configuration */
|
||||
spi_dev->sspcpsr = clk_dvsr;
|
||||
spi_dev->sspcr0 = tmp_cr0;
|
||||
|
||||
/* Default setup hard coded */
|
||||
spi_dev->sspimsc = 0;
|
||||
spi_dev->sspdmacr = 0;
|
||||
spi_dev->sspicr = (SPI_PL022_SSPICR_RORIC_MSK | SPI_PL022_SSPICR_RTIC_MSK);
|
||||
|
||||
spi_dev->sspcr1 = tmp_cr1;
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
enum spi_pl022_error_t ret;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
ret = spi_set_configuration(p_spi, &dev->cfg->default_ctrl_cfg, sys_clk);
|
||||
|
||||
if(ret != SPI_PL022_ERR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev->data->sys_clk = sys_clk;
|
||||
|
||||
/* Initilizes current SPI control configuration */
|
||||
memcpy(&dev->data->ctrl_cfg, &dev->cfg->default_ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
dev->data->state = SPI_PL022_INITIALIZED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
|
||||
{
|
||||
enum spi_pl022_error_t ret;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(ctrl_cfg == NULL) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
ret = spi_set_configuration(p_spi, ctrl_cfg, dev->data->sys_clk);
|
||||
|
||||
if(ret != SPI_PL022_ERR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Updates current SPI control configuration */
|
||||
memcpy(&dev->data->ctrl_cfg, ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
|
||||
{
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(ctrl_cfg == NULL) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* Copy current SPI control configuration */
|
||||
memcpy(ctrl_cfg, &dev->data->ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_mode_select_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
|
||||
/* Disable device */
|
||||
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
|
||||
/* Set mode */
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_MS_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_MS_POS);
|
||||
dev->data->ctrl_cfg.spi_mode = mode;
|
||||
/* Re-enable device */
|
||||
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_slave_output_mode_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_SOD_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_SOD_POS);
|
||||
}
|
||||
|
||||
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_loopback_select_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_LBM_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_LBM_POS);
|
||||
}
|
||||
|
||||
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspimsc |= (irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspimsc &= ~(irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return (p_spi->sspris & SPI_PL022_SSPRIS_VALID_MSK);
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return (p_spi->sspmis & SPI_PL022_SSPMIS_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspicr = (irq_mask & SPI_PL022_SSPICR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspdmacr |= (dma & SPI_PL022_SSPDMACR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspdmacr &= ~(dma & SPI_PL022_SSPDMACR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_periphid_t* periphid)
|
||||
{
|
||||
uint32_t tempid, tempid2;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
tempid = p_spi->sspperiphid0 & SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK;
|
||||
tempid2 = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK)
|
||||
<< SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE;
|
||||
periphid->partNumber = tempid | tempid2;
|
||||
|
||||
tempid = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK)
|
||||
>> SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS;
|
||||
tempid2 = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK)
|
||||
<< SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE;
|
||||
periphid->designerID = tempid | tempid2;
|
||||
|
||||
tempid = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK)
|
||||
>> SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE;
|
||||
periphid->revision = tempid;
|
||||
|
||||
tempid = p_spi->sspperiphid3 & SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK;
|
||||
periphid->configuration = tempid;
|
||||
}
|
||||
|
||||
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_primecell_id_t* cellid)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
cellid->cellid0 = (uint8_t) p_spi->ssppcellid0;
|
||||
cellid->cellid1 = (uint8_t) p_spi->ssppcellid1;
|
||||
cellid->cellid2 = (uint8_t) p_spi->ssppcellid2;
|
||||
cellid->cellid3 = (uint8_t) p_spi->ssppcellid3;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
uint32_t clk_dvsr;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(!sys_clk) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
clk_dvsr = spi_calc_clock_rate(&dev->data->ctrl_cfg, sys_clk, &p_spi->sspcr0);
|
||||
|
||||
if(SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
}
|
||||
|
||||
p_spi->sspcpsr = clk_dvsr;
|
||||
dev->data->sys_clk = sys_clk;
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
|
||||
void *rx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(p_spi->sspsr & SPI_PL022_SSPSR_RNE_MSK) {
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
*(uint8_t*)rx_ptr = p_spi->sspdr & WORD_1BYTE_MASK;
|
||||
} else {
|
||||
*(uint16_t*)rx_ptr = p_spi->sspdr & WORD_2BYTES_MASK;
|
||||
}
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
return SPI_PL022_ERR_NO_RX;
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
uint32_t data;
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
data = p_spi->sspdr & WORD_1BYTE_MASK;
|
||||
} else {
|
||||
data = p_spi->sspdr & WORD_2BYTES_MASK;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
|
||||
const enum spi_pl022_mode_select_t mode,
|
||||
const void *tx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(p_spi->sspsr & SPI_PL022_SSPSR_TNF_MSK){
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
p_spi->sspdr = *(const uint8_t*)tx_ptr;
|
||||
} else {
|
||||
p_spi->sspdr = *(const uint16_t*)tx_ptr;
|
||||
}
|
||||
/* Wait for write to go through */
|
||||
if (mode == SPI_PL022_MASTER_SELECT) {
|
||||
while(p_spi->sspsr & SPI_PL022_SSPSR_BSY_MSK) {};
|
||||
}
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
return SPI_PL022_ERR_NO_TX;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
|
||||
const void *tx_ptr,
|
||||
uint32_t *tx_len_ptr,
|
||||
void *rx_ptr,
|
||||
uint32_t *rx_len_ptr)
|
||||
{
|
||||
uint32_t i;
|
||||
enum spi_pl022_error_t retval = SPI_PL022_ERR_NONE;
|
||||
uint8_t word_size = 1;
|
||||
uint32_t rx_data, tx_data, total_len;
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size > 8) {
|
||||
word_size = 2;
|
||||
/* return error if sizes are not word_size aligned */
|
||||
if ((*tx_len_ptr & 0x1) || (*rx_len_ptr & 0x1)) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
total_len = (*tx_len_ptr > *rx_len_ptr) ? *tx_len_ptr : *rx_len_ptr;
|
||||
|
||||
for(i=0;i<total_len;i+=word_size){
|
||||
if (i<*tx_len_ptr) {
|
||||
tx_data = *(const uint16_t*)tx_ptr;
|
||||
} else {
|
||||
/* send FF if there is no more valid data to send */
|
||||
tx_data = 0xFFFF;
|
||||
}
|
||||
retval = spi_pl022_write(dev, dev->data->ctrl_cfg.spi_mode, &tx_data);
|
||||
if(retval != SPI_PL022_ERR_NONE) {
|
||||
*tx_len_ptr = i;
|
||||
*rx_len_ptr = i;
|
||||
break;
|
||||
}
|
||||
if(i < *tx_len_ptr) {
|
||||
tx_ptr = (const uint8_t*)tx_ptr + word_size;
|
||||
}
|
||||
retval = spi_pl022_read(dev, &rx_data);
|
||||
if(retval != SPI_PL022_ERR_NONE) {
|
||||
/* send went through, align tx_len to the updated tx_ptr */
|
||||
*tx_len_ptr = i + word_size;
|
||||
/* don't update rx_len if there is an overflow */
|
||||
if (i < *rx_len_ptr) {
|
||||
*rx_len_ptr = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* do not overflow rx buffer */
|
||||
if(i<*rx_len_ptr) {
|
||||
if (word_size == 1) {
|
||||
*(uint8_t*)rx_ptr = (uint8_t) rx_data;
|
||||
} else {
|
||||
*(uint16_t*)rx_ptr = (uint16_t) rx_data;
|
||||
}
|
||||
rx_ptr = (uint8_t*)rx_ptr + word_size;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* TEST APIs
|
||||
*/
|
||||
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr |= SPI_PL022_SSPTCR_TESTFIFO_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_TESTFIFO_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr |= SPI_PL022_SSPTCR_ITEN_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_ITEN_MSK;
|
||||
}
|
||||
|
||||
|
||||
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev,
|
||||
void *tx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
p_spi->ssptdr = *(const uint8_t*)tx_ptr;
|
||||
} else {
|
||||
p_spi->ssptdr = *(const uint16_t*)tx_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
return p_spi->sspitop;
|
||||
}
|
||||
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file spi_pl022_drv.h
|
||||
* \brief Generic driver for ARM SPI PL022.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_PL022_DRV_H__
|
||||
#define __SPI_PL022_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Frame format */
|
||||
#define SPI_PL022_CFG_FRF_MOT 0
|
||||
#define SPI_PL022_CFG_FRF_TI 1
|
||||
#define SPI_PL022_CFG_FRF_MICROWIRE 2
|
||||
|
||||
enum spi_pl022_mode_select_t {
|
||||
SPI_PL022_MASTER_SELECT = 0,
|
||||
SPI_PL022_SLAVE_SELECT,
|
||||
};
|
||||
|
||||
enum spi_pl022_slave_output_mode_t {
|
||||
SPI_PL022_SLAVE_OUTPUT_EN = 0,
|
||||
SPI_PL022_SLAVE_OUTPUT_DIS,
|
||||
};
|
||||
|
||||
enum spi_pl022_loopback_select_t {
|
||||
SPI_PL022_LOOPBACK_MODE_DIS = 0,
|
||||
SPI_PL022_LOOPBACK_MODE_EN,
|
||||
};
|
||||
|
||||
struct spi_pl022_periphid_t {
|
||||
uint32_t partNumber;
|
||||
uint32_t designerID;
|
||||
uint32_t revision;
|
||||
uint32_t configuration;
|
||||
};
|
||||
|
||||
struct spi_pl022_primecell_id_t {
|
||||
uint8_t cellid0;
|
||||
uint8_t cellid1;
|
||||
uint8_t cellid2;
|
||||
uint8_t cellid3;
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device control configuration structure */
|
||||
struct spi_pl022_ctrl_cfg_t {
|
||||
enum spi_pl022_mode_select_t spi_mode; /*!< master-slave */
|
||||
uint8_t frame_format; /*!< frame format bitmap
|
||||
clock phase [7] polarity [6]
|
||||
reserved [5:3]
|
||||
frame_format [1:0] */
|
||||
uint8_t word_size; /*!< value 4 to 16 */
|
||||
uint8_t reserved[2]; /*!< to keep 32 bits aligned */
|
||||
uint32_t bit_rate; /*!< required bit rate */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device configuration structure */
|
||||
struct spi_pl022_dev_cfg_t {
|
||||
const uint32_t base; /*!< SPI PL022 base address */
|
||||
const struct spi_pl022_ctrl_cfg_t default_ctrl_cfg; /*!< Default SPI
|
||||
configuration */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device data structure */
|
||||
struct spi_pl022_dev_data_t {
|
||||
uint32_t state; /*!< SPI driver state */
|
||||
uint32_t sys_clk; /*!< System clock frequency */
|
||||
struct spi_pl022_ctrl_cfg_t ctrl_cfg; /*!< SPI control
|
||||
configuration data */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device structure */
|
||||
struct spi_pl022_dev_t {
|
||||
const struct spi_pl022_dev_cfg_t* const cfg; /*!< SPI driver
|
||||
configuration */
|
||||
struct spi_pl022_dev_data_t* const data; /*!< SPI driver data */
|
||||
};
|
||||
|
||||
enum spi_pl022_error_t {
|
||||
SPI_PL022_ERR_NONE = 0, /*!< No error */
|
||||
SPI_PL022_ERR_INVALID_ARGS, /*!< Invalid input arguments */
|
||||
SPI_PL022_ERR_NOT_INIT, /*!< SPI driver is not initialized */
|
||||
SPI_PL022_ERR_NO_TX, /*!< SPI transm FIFO full */
|
||||
SPI_PL022_ERR_NO_RX, /*!< SPI receive FIFO empty */
|
||||
SPI_PL022_ERR_BAD_CONFIG, /*!< Bad SPI configuration */
|
||||
};
|
||||
|
||||
|
||||
/* Interrupt mask defines for the interrupt APIs */
|
||||
|
||||
/* Receive Overrun Interrupt */
|
||||
#define SPI_PL022_RX_OR_INTR_POS 0
|
||||
#define SPI_PL022_RX_OR_INTR_MSK (0x1ul<<SPI_PL022_RX_OR_INTR_POS)
|
||||
|
||||
/* Receive Timeout Interrupt */
|
||||
#define SPI_PL022_RX_TO_INTR_POS 1
|
||||
#define SPI_PL022_RX_TO_INTR_MSK (0x1ul<<SPI_PL022_RX_TO_INTR_POS)
|
||||
|
||||
/* Receive FIFO Interrupt */
|
||||
#define SPI_PL022_RX_FIFO_INTR_POS 2
|
||||
#define SPI_PL022_RX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_RX_FIFO_INTR_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt */
|
||||
#define SPI_PL022_TX_FIFO_INTR_POS 3
|
||||
#define SPI_PL022_TX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_TX_FIFO_INTR_POS)
|
||||
|
||||
#define SPI_PL022_ALL_INTR_MSK \
|
||||
((0x1ul<<(SPI_PL022_TX_FIFO_INTR_POS+1))-1)
|
||||
|
||||
/* Status register bit defines */
|
||||
|
||||
/* Transmit FIFO empty */
|
||||
#define SPI_PL022_SSPSR_TFE_POS 0
|
||||
#define SPI_PL022_SSPSR_TFE_MSK (0x1ul<<SPI_PL022_SSPSR_TFE_POS)
|
||||
|
||||
/* Transmit FIFO not full */
|
||||
#define SPI_PL022_SSPSR_TNF_POS 1
|
||||
#define SPI_PL022_SSPSR_TNF_MSK (0x1ul<<SPI_PL022_SSPSR_TNF_POS)
|
||||
|
||||
/* Receive FIFO not empty */
|
||||
#define SPI_PL022_SSPSR_RNE_POS 2
|
||||
#define SPI_PL022_SSPSR_RNE_MSK (0x1ul<<SPI_PL022_SSPSR_RNE_POS)
|
||||
|
||||
/* Receive FIFO full */
|
||||
#define SPI_PL022_SSPSR_RFF_POS 3
|
||||
#define SPI_PL022_SSPSR_RFF_MSK (0x1ul<<SPI_PL022_SSPSR_RFF_POS)
|
||||
|
||||
/* Busy either tx/rx or transmit fifo not empty */
|
||||
#define SPI_PL022_SSPSR_BSY_POS 4
|
||||
#define SPI_PL022_SSPSR_BSY_MSK (0x1ul<<SPI_PL022_SSPSR_BSY_POS)
|
||||
|
||||
/**
|
||||
* \brief Enables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns SPI status register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Initializes the SPI PL022 device.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] ctrl_cfg SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
|
||||
|
||||
/**
|
||||
* \brief Gets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] ctrl_cfg Pointer to fill the SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects SPI PL022 device as Master or Slave
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_mode_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_mode_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables/disables SPI PL022 Slave device output
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_slave_output_mode_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
* \note This function doesn't check if dev is Slave or Master
|
||||
*/
|
||||
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_slave_output_mode_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables SPI PL022 device in loopback mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_loopback_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_loopback_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Clears interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to enable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Gets raw interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns raw interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets masked interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns masked interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Enables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be enabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Disables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be disabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Gets peripheral identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] periphid Pointer to fill peripheral ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_periphid_t* periphid);
|
||||
|
||||
/**
|
||||
* \brief Gets PrimeCell identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] cellid Pointer to fill PrimeCell ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_primecell_id_t* cellid);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* must be enough for configured word size
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
|
||||
void *rx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from slave SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns data value from the device
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* does not validate whether there is any data in the RX buffer
|
||||
*/
|
||||
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Writes single data to SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Master or slave \ref spi_pl022_mode_select_t
|
||||
* \param[out] tx_ptr Pointer to the data to be sent
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
|
||||
const enum spi_pl022_mode_select_t mode,
|
||||
const void *tx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Transmit and Receive data on SPI in a blocking call
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] tx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] tx_len_ptr Num values to transfer (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] rx_len_ptr Num values to receive (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
|
||||
const void *tx_ptr,
|
||||
uint32_t *tx_len_ptr,
|
||||
void *rx_ptr,
|
||||
uint32_t *rx_len_ptr);
|
||||
|
||||
|
||||
/************************** TEST APIs ****************************/
|
||||
|
||||
/**
|
||||
* \brief Enables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Writes data to Test data register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* whether Test FIFO mode is enabled
|
||||
*/
|
||||
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, void *tx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads integration test output register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __SPI_PL022_DRV_H__ */
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file timer_cmsdk_drv.c
|
||||
* \brief Generic driver for CMSDK APB Timers.
|
||||
* The timer is a 32-bit down-counter with the following features:
|
||||
* - optional programmable external clock source
|
||||
* - programmable interrupt source, triggered if counter reaches 0
|
||||
* - automatic reload if counter reaches 0
|
||||
*/
|
||||
|
||||
#include "timer_cmsdk_drv.h"
|
||||
|
||||
/** Setter bit manipulation macro */
|
||||
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
|
||||
/** Clearing bit manipulation macro */
|
||||
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
|
||||
/** Getter bit manipulation macro */
|
||||
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
|
||||
|
||||
/**
|
||||
* \brief Timer register map structure
|
||||
*
|
||||
*/
|
||||
struct timer_cmsdk_reg_map_t {
|
||||
volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */
|
||||
volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */
|
||||
volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */
|
||||
union {
|
||||
volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt
|
||||
* status register */
|
||||
volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt
|
||||
* clear register */
|
||||
}intreg;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief CTRL register bit definitions
|
||||
*
|
||||
*/
|
||||
enum ctrl_reg_bits_t{
|
||||
CTRL_REG_ENUM_ENABLE_INDEX = 0,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
|
||||
CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief INTSTATUS/INTCLEAR register bit definitions
|
||||
*
|
||||
*/
|
||||
enum interrupt_reg_bits_t{
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
|
||||
};
|
||||
|
||||
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if (dev->data->is_initialized == 0) {
|
||||
register_map->ctrl = 0;
|
||||
register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
|
||||
dev->data->is_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
return dev->data->is_initialized;
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->intreg.intstatus,
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->intreg.intclear,
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->value;
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
|
||||
uint32_t reload)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
register_map->reload = reload;
|
||||
}
|
||||
|
||||
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
register_map->value = register_map->reload;
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->reload;
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->reload - register_map->value;
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file timer_cmsdk_drv.h
|
||||
* \brief Generic driver for CMSDK APB Timers.
|
||||
* The timer is a 32-bit down-counter with the following features:
|
||||
* - optional programmable external clock source
|
||||
* - programmable interrupt source, triggered if counter reaches 0
|
||||
* - automatic reload if counter reaches 0
|
||||
*/
|
||||
|
||||
#ifndef __TIMER_CMSDK_DRV_H__
|
||||
#define __TIMER_CMSDK_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Maximum reload value */
|
||||
#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */
|
||||
#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD
|
||||
|
||||
/** CMSDK timer device configuration structure */
|
||||
struct timer_cmsdk_dev_cfg_t {
|
||||
const uintptr_t base; /*!< Timer base address */
|
||||
};
|
||||
|
||||
/** CMSDK timer device data structure */
|
||||
struct timer_cmsdk_dev_data_t {
|
||||
bool is_initialized; /*!< Indicates if the timer is initialized */
|
||||
};
|
||||
|
||||
/* CMSDK timer device structure */
|
||||
struct timer_cmsdk_dev_t {
|
||||
const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */
|
||||
struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes timer to a known default state, which is:
|
||||
* - timer disabled
|
||||
* - timer interrupt disabled
|
||||
* - clock source set to internal
|
||||
* - external input disabled
|
||||
* - reload value maxed out
|
||||
* Init should be called prior to any other process and
|
||||
* it's the caller's responsibility to follow proper call order.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer is initialized.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if initialized, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables external input, which could be used as clock source
|
||||
* by calling \ref timer_cmsdk_set_clock_to_external.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables external input.
|
||||
* Make sure if the timer is explicitly wanted to be stopped or set
|
||||
* the clock source to internal by \ref timer_cmsdk_set_clock_to_internal.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if external input is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the clock source to internal.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the clock source to external.
|
||||
* Make sure external input is enabled correspondingly
|
||||
* by \ref timer_cmsdk_enable_external_input.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if clock source is external input.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if external, false if internal
|
||||
*/
|
||||
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables timer operation.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables the given hardware timer.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables timer interrupt.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables timer interrupt.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer interrupt is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets timer interrupt status
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* * \return true if active, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears timer interrupt
|
||||
* The interrupt request is held until it is cleared.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reads timer current value.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Timer value
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the reload value of the selected timer.
|
||||
*
|
||||
* New reload value takes effect when:
|
||||
* - timer is restarted
|
||||
* - on timer underflow
|
||||
* - when timer_cmsdk_reset is called
|
||||
*
|
||||
* \note In r1p0 technical reference manual it's incorrectly stated
|
||||
* writing the reload value automatically sets the current value also.
|
||||
* r1p1 technical reference manual includes the fix.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
* \param[in] reload Timer reload value to set.
|
||||
* This is the start value of the 32-bit down counter,
|
||||
* which automatically reloaded if 0 is reached.
|
||||
*/
|
||||
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
|
||||
uint32_t reload);
|
||||
|
||||
/**
|
||||
* \brief Resets the timer counter to the reload value instantly
|
||||
* (i.e. without waiting for underflow).
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets the reload value of the selected timer.
|
||||
* This is the start value of the 32-bit down counter,
|
||||
* which is automatically reloaded if 0 is reached by the counter.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Reload value of the selected timer.
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reads the number of ticks elapsed in the current cycle.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Get elapsed number of ticks since last reload was set.
|
||||
* Elapsed = (Reload value - Current value)
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __TIMER_CMSDK_DRV_H__ */
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "platform_devices.h"
|
||||
#include "SMM_MPS2.h"
|
||||
|
||||
/* ARM CMSDK Timer driver structures */
|
||||
#ifdef ARM_CMSDK_TIMER0
|
||||
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG = {
|
||||
.base = CMSDK_TIMER0_BASE};
|
||||
static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA = {
|
||||
.is_initialized = 0};
|
||||
struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV = {&(CMSDK_TIMER0_DEV_CFG),
|
||||
&(CMSDK_TIMER0_DEV_DATA)};
|
||||
#endif
|
||||
|
||||
#ifdef ARM_CMSDK_TIMER1
|
||||
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG = {
|
||||
.base = CMSDK_TIMER1_BASE};
|
||||
static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA = {
|
||||
.is_initialized = 0};
|
||||
struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV = {&(CMSDK_TIMER1_DEV_CFG),
|
||||
&(CMSDK_TIMER1_DEV_DATA)};
|
||||
#endif
|
||||
|
||||
/* ARM GPIO driver structures */
|
||||
#ifdef ARM_GPIO0
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO0_DEV_CFG = {
|
||||
.base = CMSDK_GPIO0_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO0_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO0_DEV = {&(ARM_GPIO0_DEV_CFG),
|
||||
&(ARM_GPIO0_DEV_DATA)};
|
||||
#endif /* ARM_GPIO0 */
|
||||
|
||||
#ifdef ARM_GPIO1
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO1_DEV_CFG = {
|
||||
.base = CMSDK_GPIO1_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO1_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO1_DEV = {&(ARM_GPIO1_DEV_CFG),
|
||||
&(ARM_GPIO1_DEV_DATA)};
|
||||
#endif /* ARM_GPIO1 */
|
||||
|
||||
#ifdef ARM_GPIO2
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO2_DEV_CFG = {
|
||||
.base = CMSDK_GPIO2_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO2_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO2_DEV = {&(ARM_GPIO2_DEV_CFG),
|
||||
&(ARM_GPIO2_DEV_DATA)};
|
||||
#endif /* ARM_GPIO2 */
|
||||
|
||||
#ifdef ARM_GPIO3
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO3_DEV_CFG = {
|
||||
.base = CMSDK_GPIO3_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO3_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO3_DEV = {&(ARM_GPIO3_DEV_CFG),
|
||||
&(ARM_GPIO3_DEV_DATA)};
|
||||
#endif /* ARM_GPIO3 */
|
||||
|
||||
/* ARM MPS2 IO FPGAIO driver structures */
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_FPGAIO_DEV_CFG = {
|
||||
.base = MPS2_FPGAIO_BASE,
|
||||
.type = ARM_MPS2_IO_TYPE_FPGAIO};
|
||||
struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV =
|
||||
{&(ARM_MPS2_IO_FPGAIO_DEV_CFG)};
|
||||
#endif /* ARM_MPS2_IO_FPGAIO */
|
||||
|
||||
/* ARM MPS2 IO SCC driver structures */
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_SCC_DEV_CFG = {
|
||||
/*
|
||||
* MPS2 IO SCC and FPGAIO registers have similar structure
|
||||
* with 4 byte offset addresses.
|
||||
*/
|
||||
.base = MPS2_SCC_BASE + 4,
|
||||
.type = ARM_MPS2_IO_TYPE_SCC};
|
||||
struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV = {&(ARM_MPS2_IO_SCC_DEV_CFG)};
|
||||
#endif /* ARM_MPS2_IO_SCC */
|
||||
|
||||
/* ARM SPI driver structure */
|
||||
#ifdef ARM_SPI0
|
||||
static const struct spi_pl022_dev_cfg_t SPI0_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP0_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI0_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI0_PL022_DEV = {&(SPI0_PL022_DEV_CFG),
|
||||
&(SPI0_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI0 */
|
||||
|
||||
#ifdef ARM_SPI1
|
||||
static const struct spi_pl022_dev_cfg_t SPI1_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP1_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI1_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI1_PL022_DEV = {&(SPI1_PL022_DEV_CFG),
|
||||
&(SPI1_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI1 */
|
||||
|
||||
#ifdef ARM_SPI2
|
||||
static const struct spi_pl022_dev_cfg_t SPI2_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP2_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI2_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI2_PL022_DEV = {&(SPI2_PL022_DEV_CFG),
|
||||
&(SPI2_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI2 */
|
||||
|
||||
#ifdef ARM_SPI3
|
||||
static const struct spi_pl022_dev_cfg_t SPI3_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP3_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI3_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI3_PL022_DEV = {&(SPI3_PL022_DEV_CFG),
|
||||
&(SPI3_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI3 */
|
||||
|
||||
#ifdef ARM_SPI4
|
||||
static const struct spi_pl022_dev_cfg_t SPI4_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP4_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI4_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI4_PL022_DEV = {&(SPI4_PL022_DEV_CFG),
|
||||
&(SPI4_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI4 */
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART0_DEV_CFG = {
|
||||
.base = CMSDK_UART0_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART0_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART0_DEV = {&(ARM_UART0_DEV_CFG),
|
||||
&(ARM_UART0_DEV_DATA)};
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
#ifdef ARM_UART1
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART1_DEV_CFG = {
|
||||
.base = CMSDK_UART1_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART1_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART1_DEV = {&(ARM_UART1_DEV_CFG),
|
||||
&(ARM_UART1_DEV_DATA)};
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
#ifdef ARM_UART2
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART2_DEV_CFG = {
|
||||
.base = CMSDK_UART2_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART2_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART2_DEV = {&(ARM_UART2_DEV_CFG),
|
||||
&(ARM_UART2_DEV_DATA)};
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
#ifdef ARM_UART3
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART3_DEV_CFG = {
|
||||
.base = CMSDK_UART3_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART3_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART3_DEV = {&(ARM_UART3_DEV_CFG),
|
||||
&(ARM_UART3_DEV_DATA)};
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
#ifdef ARM_UART4
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART4_DEV_CFG = {
|
||||
.base = CMSDK_UART4_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG),
|
||||
&(ARM_UART4_DEV_DATA)};
|
||||
#endif /* ARM_UART4 */
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_LTD_PLATFORM_DEVICES_H__
|
||||
#define __ARM_LTD_PLATFORM_DEVICES_H__
|
||||
|
||||
#include "device_cfg.h"
|
||||
|
||||
/* ======= Includes generic driver headers ======= */
|
||||
#include "timer_cmsdk_drv.h"
|
||||
#include "arm_gpio_drv.h"
|
||||
#include "arm_mps2_io_drv.h"
|
||||
#include "spi_pl022_drv.h"
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
/* ======= Defines peripheral configuration structures ======= */
|
||||
|
||||
/* ARM CMSDK Timer driver structures */
|
||||
#ifdef ARM_CMSDK_TIMER0
|
||||
extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV;
|
||||
#endif
|
||||
|
||||
#ifdef ARM_CMSDK_TIMER1
|
||||
extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM GPIO driver structures */
|
||||
#ifdef ARM_GPIO0
|
||||
extern struct arm_gpio_dev_t ARM_GPIO0_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO1
|
||||
extern struct arm_gpio_dev_t ARM_GPIO1_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO2
|
||||
extern struct arm_gpio_dev_t ARM_GPIO2_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO3
|
||||
extern struct arm_gpio_dev_t ARM_GPIO3_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO FPGAIO driver structures */
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO SCC driver structures */
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM SPI driver structures */
|
||||
#ifdef ARM_SPI0
|
||||
extern struct spi_pl022_dev_t SPI0_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI1
|
||||
extern struct spi_pl022_dev_t SPI1_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI2
|
||||
extern struct spi_pl022_dev_t SPI2_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI3
|
||||
extern struct spi_pl022_dev_t SPI3_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI4
|
||||
extern struct spi_pl022_dev_t SPI4_PL022_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
extern struct arm_uart_dev_t ARM_UART0_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART1
|
||||
extern struct arm_uart_dev_t ARM_UART1_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART2
|
||||
extern struct arm_uart_dev_t ARM_UART2_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART3
|
||||
extern struct arm_uart_dev_t ARM_UART3_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART4
|
||||
extern struct arm_uart_dev_t ARM_UART4_DEV;
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,177 +17,236 @@
|
|||
#include <stddef.h>
|
||||
#include "gpio_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "objects.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define GPIO_PIN_POS_MASK 0x0F /* pin % 16 */
|
||||
#define RESERVED_MISC_PIN 7
|
||||
enum io_type {
|
||||
GPIO_DEVICE,
|
||||
MPS2_IO_DEVICE,
|
||||
DEVICE_UNKNOWN
|
||||
};
|
||||
|
||||
/* \brief Gets the FPGA MISC (Miscellaneous control) bit position for the given
|
||||
* pin name
|
||||
*
|
||||
* FPGA MISC bit mapping:
|
||||
* [31:7] Reserved
|
||||
* [6] CLCD_BL_CTRL
|
||||
* [5] CLCD_RD
|
||||
* [4] CLCD_RS
|
||||
* [3] CLCD_RESET
|
||||
* [2] Reserved
|
||||
* [1] SPI_nSS
|
||||
* [0] CLCD_CS
|
||||
*
|
||||
* \param[in] pin MISC pin name
|
||||
*
|
||||
* \return FPGA MISC bit position
|
||||
*/
|
||||
static uint8_t get_fpga_misc_pin_pos(PinName pin)
|
||||
/* Tell if the gpio is from GPIO device or MPS2 IO */
|
||||
static enum io_type io_type(gpio_t *obj)
|
||||
{
|
||||
uint8_t pin_position = RESERVED_MISC_PIN;
|
||||
|
||||
if (pin == SPI_SCLK) {
|
||||
pin_position = 0;
|
||||
} else if (pin == CLCD_SSEL) {
|
||||
pin_position = 1;
|
||||
} else if (pin == CLCD_RESET) {
|
||||
pin_position = 3;
|
||||
} else if (pin == CLCD_RS) {
|
||||
pin_position = 4;
|
||||
} else if (pin == CLCD_RD) {
|
||||
pin_position = 5;
|
||||
} else if (pin == CLCD_BL_CTRL){
|
||||
pin_position = 6;
|
||||
if (obj->gpio_dev != NULL && obj->mps2_io_dev == NULL) {
|
||||
return GPIO_DEVICE;
|
||||
}
|
||||
|
||||
return pin_position;
|
||||
if (obj->gpio_dev == NULL && obj->mps2_io_dev != NULL) {
|
||||
return MPS2_IO_DEVICE;
|
||||
}
|
||||
return DEVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Return the correct mask of the given PIN */
|
||||
uint32_t gpio_set(PinName pin)
|
||||
{
|
||||
uint8_t pin_position;
|
||||
pin_function(pin, (int)GPIO_FUNC);
|
||||
|
||||
if (pin >=EXP0 && pin <= EXP51) {
|
||||
/* Set pin functinality as GPIO. pin_function asserts if pin == NC */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
return (1 << GPIO_PIN_NUMBER(pin));
|
||||
} else if (pin == USERLED1 || pin == USERLED2) {
|
||||
/* User LEDs */
|
||||
return (1 << (pin - USERLED1));
|
||||
} else if (pin == USERSW1 || pin == USERSW2) {
|
||||
/* User Push buttons */
|
||||
return (1 << (pin - USERSW1));
|
||||
} else if (pin >= LED1 && pin <= LED8) {
|
||||
/* MCC LEDs */
|
||||
return (1 << (pin - LED1));
|
||||
} else if (pin >= SW1 && pin <= SW8) {
|
||||
/* MCC Switches */
|
||||
return (1 << (pin - SW1));
|
||||
} else {
|
||||
/* Check if pin is a MISC pin */
|
||||
pin_position = get_fpga_misc_pin_pos(pin);
|
||||
if (pin_position != RESERVED_MISC_PIN) {
|
||||
return (1 << pin_position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return pin mask */
|
||||
return (1 << (pin & 0xFF));
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
uint8_t pin_position;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
|
||||
if (pin == NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj->pin = pin;
|
||||
obj->pin_number = pin;
|
||||
|
||||
if (pin <= EXP15) {
|
||||
obj->reg_data = &CMSDK_GPIO0->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO0->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO0->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO0->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = pin;
|
||||
} else if (pin >= EXP16 && pin <= EXP31) {
|
||||
obj->reg_data = &CMSDK_GPIO1->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO1->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO1->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO1->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin >= EXP32 && pin <= EXP47) {
|
||||
obj->reg_data = &CMSDK_GPIO2->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO2->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO2->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO2->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin >= EXP48 && pin <= EXP51) {
|
||||
obj->reg_data = &CMSDK_GPIO3->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO3->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO3->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO3->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin == 100 || pin == 101) {
|
||||
/* User LEDs */
|
||||
pin_position = (pin - 100);
|
||||
obj->reg_data = &MPS2_FPGAIO->LED;
|
||||
obj->reg_in = &MPS2_FPGAIO->LED;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin == 110 || pin == 111) {
|
||||
/* User buttons */
|
||||
pin_position = (pin - 110);
|
||||
obj->reg_data = &MPS2_FPGAIO->BUTTON;
|
||||
obj->reg_in = &MPS2_FPGAIO->BUTTON;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin >= 200 && pin <= 207) {
|
||||
/* MCC LEDs */
|
||||
pin_position = (pin - 200);
|
||||
obj->reg_data = &MPS2_SCC->LEDS;
|
||||
obj->reg_in = &MPS2_SCC->LEDS;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin >= 210 && pin <= 217) {
|
||||
/* MCC switches */
|
||||
pin_position = (pin - 210);
|
||||
obj->reg_in = &MPS2_SCC->SWITCHES;
|
||||
obj->reg_data = NULL;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else {
|
||||
/* Check if pin is a MISC pin */
|
||||
pin_position = get_fpga_misc_pin_pos(pin);
|
||||
if (pin_position != RESERVED_MISC_PIN) {
|
||||
obj->reg_data = &MPS2_FPGAIO->MISC;
|
||||
} else {
|
||||
pin_position = 0;
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case GPIO0_NUMBER:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case GPIO1_NUMBER:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case GPIO2_NUMBER:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case GPIO3_NUMBER:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d, associated with expansion pin %d, is disabled",
|
||||
GPIO_DEV_NUMBER(pin), pin);
|
||||
return;
|
||||
}
|
||||
|
||||
arm_gpio_init(gpio_dev);
|
||||
|
||||
obj->gpio_dev = gpio_dev;
|
||||
obj->mps2_io_dev = NULL;
|
||||
obj->pin_number = GPIO_PIN_NUMBER(pin);
|
||||
/* GPIO is input by default */
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set pin mask */
|
||||
obj->mask = (1 << pin_position);
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
if (pin == USERLED1 || pin == USERLED2) {
|
||||
/* User LEDs */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV;
|
||||
obj->pin_number = pin - USERLED1;
|
||||
obj->direction = PIN_OUTPUT;
|
||||
return;
|
||||
} else if (pin == USERSW1 || pin == USERSW2) {
|
||||
/* User Push buttons */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV;
|
||||
obj->pin_number = pin - USERSW1;
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
#endif /* ARM_MPS2_IO_FPGAIO */
|
||||
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
if (pin >= LED1 && pin <= LED8) {
|
||||
/* MCC LEDs */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV;
|
||||
obj->pin_number = pin - LED1;
|
||||
obj->direction = PIN_OUTPUT;
|
||||
return;
|
||||
} else if (pin >= SW1 && pin <= SW8) {
|
||||
/* MCC Switches */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV;
|
||||
obj->pin_number = pin - SW1;
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
#endif /* ARM_MPS2_IO_SCC */
|
||||
|
||||
error("pin %d is not a GPIO", pin);
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
{
|
||||
pin_mode(obj->pin, mode);
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||
{
|
||||
if (obj->pin >= EXP0 && obj->pin <= EXP51) {
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
switch (direction) {
|
||||
case PIN_INPUT :
|
||||
*obj->reg_dirclr = obj->mask;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
*obj->reg_dir |= obj->mask;
|
||||
break;
|
||||
case PIN_INPUT:
|
||||
flags |= ARM_GPIO_INPUT;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
flags |= ARM_GPIO_OUTPUT;
|
||||
break;
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, flags);
|
||||
return;
|
||||
case MPS2_IO_DEVICE:
|
||||
/* Do nothing as MPS2 IO direction can not be changed */
|
||||
return;
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not change the direction of pin");
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
if (obj->pin != (PinName)NC) {
|
||||
if (obj->pin_number == (uint32_t)NC) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
(void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, (uint32_t)value);
|
||||
return;
|
||||
case MPS2_IO_DEVICE:
|
||||
if (obj->direction == PIN_INPUT) {
|
||||
/*
|
||||
* If the given gpio is in fact a button, ignore the call to not
|
||||
* write to the corresponding LED instead.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
arm_mps2_io_write_leds(obj->mps2_io_dev, ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number, (uint32_t)value);
|
||||
return;
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not write pin");
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t *obj)
|
||||
{
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
case MPS2_IO_DEVICE:
|
||||
switch (obj->direction) {
|
||||
case PIN_INPUT:
|
||||
|
||||
return (int)arm_mps2_io_read_buttons(obj->mps2_io_dev,
|
||||
ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
case PIN_OUTPUT:
|
||||
return (int)arm_mps2_io_read_leds(obj->mps2_io_dev,
|
||||
ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
}
|
||||
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not read pin");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,425 +14,192 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "cmsis.h"
|
||||
#include "objects.h"
|
||||
#include "gpio_irq_api.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define CHANNEL_NUM 32
|
||||
#define CMSDK_GPIO_0 CMSDK_GPIO0
|
||||
#define CMSDK_GPIO_1 CMSDK_GPIO1
|
||||
#define PININT_IRQ 0
|
||||
#define ERROR_BIT_NUMBER 0xFF
|
||||
|
||||
static uint32_t channel_ids[CHANNEL_NUM] = {0};
|
||||
static gpio_irq_handler irq_handler;
|
||||
struct gpio_irq_handler_t {
|
||||
gpio_irq_handler handler;
|
||||
gpio_irq_event event;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
static inline void handle_interrupt_in(uint32_t channel)
|
||||
/* Handlers registered */
|
||||
static struct gpio_irq_handler_t gpio_irq[PINS_NUMBER];
|
||||
|
||||
/*
|
||||
* Return the bit number of the lowest significant bit set to 1 or
|
||||
* ERROR_BIT_NUMBER if there is no bit set.
|
||||
*/
|
||||
static uint8_t find_first_set_bit(uint32_t word)
|
||||
{
|
||||
uint32_t ch_bit = (1 << channel);
|
||||
// Return immediately if:
|
||||
// * The interrupt was already served
|
||||
// * There is no user handler
|
||||
// * It is a level interrupt, not an edge interrupt
|
||||
if (ch_bit < 16) {
|
||||
if (((CMSDK_GPIO_0->INTSTATUS) == 0)
|
||||
|| (channel_ids[channel] == 0)
|
||||
|| ((CMSDK_GPIO_0->INTTYPESET) == 0) ) {
|
||||
return;
|
||||
}
|
||||
uint8_t bit_number = 0;
|
||||
|
||||
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_RISE);
|
||||
CMSDK_GPIO_0->INTPOLSET = ch_bit;
|
||||
}
|
||||
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_FALL);
|
||||
}
|
||||
|
||||
CMSDK_GPIO_0->INTCLEAR = ch_bit;
|
||||
} else {
|
||||
if (((CMSDK_GPIO_1->INTSTATUS) == 0)
|
||||
|| (channel_ids[channel] == 0)
|
||||
|| ((CMSDK_GPIO_1->INTTYPESET) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_RISE);
|
||||
CMSDK_GPIO_1->INTPOLSET = ch_bit;
|
||||
}
|
||||
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_FALL);
|
||||
}
|
||||
CMSDK_GPIO_1->INTCLEAR = ch_bit;
|
||||
if (word == 0) {
|
||||
return ERROR_BIT_NUMBER;
|
||||
}
|
||||
|
||||
while (((word >> bit_number++) & 1UL) == 0);
|
||||
|
||||
return (bit_number - 1);
|
||||
}
|
||||
|
||||
void gpio0_irq0(void)
|
||||
static void handler(struct arm_gpio_dev_t* dev, uint32_t gpio_number,
|
||||
uint32_t exp_pin_base)
|
||||
{
|
||||
handle_interrupt_in(0);
|
||||
uint32_t irq_status = 0;
|
||||
/* Pin that triggered the IRQ in this GPIO */
|
||||
uint8_t pin_number;
|
||||
/* Pin number in the expension port */
|
||||
uint8_t exp_pin_number;
|
||||
|
||||
(void)arm_gpio_get_irq_status(dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
&irq_status);
|
||||
|
||||
pin_number = find_first_set_bit(irq_status);
|
||||
if (pin_number == ERROR_BIT_NUMBER) {
|
||||
/* There was no IRQ */
|
||||
return;
|
||||
}
|
||||
|
||||
(void)arm_gpio_clear_interrupt(dev, pin_number);
|
||||
|
||||
exp_pin_number = exp_pin_base + pin_number;
|
||||
|
||||
gpio_irq[exp_pin_number].handler(gpio_irq[exp_pin_number].id,
|
||||
gpio_irq[exp_pin_number].event);
|
||||
}
|
||||
|
||||
void gpio0_irq1(void)
|
||||
#ifdef ARM_GPIO0
|
||||
void PORT0_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(1);
|
||||
handler(&ARM_GPIO0_DEV, GPIO0_NUMBER, EXP_PIN_BASE0);
|
||||
}
|
||||
#endif /* ARM_GPIO0 */
|
||||
|
||||
void gpio0_irq2(void)
|
||||
#ifdef ARM_GPIO1
|
||||
void PORT1_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(2);
|
||||
handler(&ARM_GPIO1_DEV, GPIO1_NUMBER, EXP_PIN_BASE1);
|
||||
}
|
||||
#endif /* ARM_GPIO1 */
|
||||
|
||||
void gpio0_irq3(void)
|
||||
#ifdef ARM_GPIO2
|
||||
void PORT2_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(3);
|
||||
handler(&ARM_GPIO2_DEV, GPIO2_NUMBER, EXP_PIN_BASE2);
|
||||
}
|
||||
#endif /* ARM_GPIO2 */
|
||||
|
||||
void gpio0_irq4(void)
|
||||
#ifdef ARM_GPIO3
|
||||
void PORT3_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(4);
|
||||
handler(&ARM_GPIO3_DEV, GPIO3_NUMBER, EXP_PIN_BASE3);
|
||||
}
|
||||
#endif /* ARM_GPIO3 */
|
||||
|
||||
void gpio0_irq5(void)
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
|
||||
uint32_t id)
|
||||
{
|
||||
handle_interrupt_in(5);
|
||||
}
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
|
||||
void gpio0_irq6(void)
|
||||
{
|
||||
handle_interrupt_in(6);
|
||||
}
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case 0:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
obj->irq_number = PORT0_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case 1:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
obj->irq_number = PORT1_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case 2:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
obj->irq_number = PORT2_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case 3:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
obj->irq_number = PORT3_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d is not enabled", GPIO_DEV_NUMBER(pin));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void gpio0_irq7(void)
|
||||
{
|
||||
handle_interrupt_in(7);
|
||||
}
|
||||
obj->gpio_dev = gpio_dev;
|
||||
obj->pin_number = GPIO_PIN_NUMBER(pin);
|
||||
obj->exp_pin_number = pin;
|
||||
|
||||
void gpio0_irq8(void)
|
||||
{
|
||||
handle_interrupt_in(8);
|
||||
}
|
||||
arm_gpio_init(gpio_dev);
|
||||
|
||||
void gpio0_irq9(void)
|
||||
{
|
||||
handle_interrupt_in(9);
|
||||
}
|
||||
/* Save the handler and id into the global structure */
|
||||
gpio_irq[pin].handler = handler;
|
||||
gpio_irq[pin].id = id;
|
||||
|
||||
void gpio0_irq10(void)
|
||||
{
|
||||
handle_interrupt_in(10);
|
||||
}
|
||||
|
||||
void gpio0_irq11(void)
|
||||
{
|
||||
handle_interrupt_in(11);
|
||||
}
|
||||
|
||||
void gpio0_irq12(void)
|
||||
{
|
||||
handle_interrupt_in(12);
|
||||
}
|
||||
|
||||
void gpio0_irq13(void)
|
||||
{
|
||||
handle_interrupt_in(13);
|
||||
}
|
||||
|
||||
void gpio0_irq14(void)
|
||||
{
|
||||
handle_interrupt_in(14);
|
||||
}
|
||||
|
||||
void gpio0_irq15(void)
|
||||
{
|
||||
handle_interrupt_in(15);
|
||||
}
|
||||
|
||||
void gpio1_irq0(void)
|
||||
{
|
||||
handle_interrupt_in(16);
|
||||
}
|
||||
|
||||
void gpio1_irq1(void)
|
||||
{
|
||||
handle_interrupt_in(17);
|
||||
}
|
||||
void gpio1_irq2(void)
|
||||
{
|
||||
handle_interrupt_in(18);
|
||||
}
|
||||
|
||||
void gpio1_irq3(void)
|
||||
{
|
||||
handle_interrupt_in(19);
|
||||
}
|
||||
|
||||
void gpio1_irq4(void)
|
||||
{
|
||||
handle_interrupt_in(20);
|
||||
}
|
||||
|
||||
void gpio1_irq5(void)
|
||||
{
|
||||
handle_interrupt_in(21);
|
||||
}
|
||||
|
||||
void gpio1_irq6(void)
|
||||
{
|
||||
handle_interrupt_in(22);
|
||||
}
|
||||
|
||||
void gpio1_irq7(void)
|
||||
{
|
||||
handle_interrupt_in(23);
|
||||
}
|
||||
|
||||
void gpio1_irq8(void)
|
||||
{
|
||||
handle_interrupt_in(24);
|
||||
}
|
||||
|
||||
void gpio1_irq9(void)
|
||||
{
|
||||
handle_interrupt_in(25);
|
||||
}
|
||||
|
||||
void gpio1_irq10(void)
|
||||
{
|
||||
handle_interrupt_in(26);
|
||||
}
|
||||
|
||||
void gpio1_irq11(void)
|
||||
{
|
||||
handle_interrupt_in(27);
|
||||
}
|
||||
|
||||
void gpio1_irq12(void)
|
||||
{
|
||||
handle_interrupt_in(28);
|
||||
}
|
||||
|
||||
void gpio1_irq13(void)
|
||||
{
|
||||
handle_interrupt_in(29);
|
||||
}
|
||||
|
||||
void gpio1_irq14(void)
|
||||
{
|
||||
handle_interrupt_in(30);
|
||||
}
|
||||
|
||||
void gpio1_irq15(void)
|
||||
{
|
||||
handle_interrupt_in(31);
|
||||
}
|
||||
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin,
|
||||
gpio_irq_handler handler, uint32_t id)
|
||||
{
|
||||
int found_free_channel = 0;
|
||||
int i = 0;
|
||||
|
||||
if (pin == NC) {
|
||||
return 0;
|
||||
} else {
|
||||
/* The pin is not concerned with GPIO IRQ */
|
||||
error("Pin %d is not a GPIO", pin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq_handler = handler;
|
||||
|
||||
for (i=0; i<CHANNEL_NUM; i++) {
|
||||
if (channel_ids[i] == 0) {
|
||||
channel_ids[i] = id;
|
||||
obj->ch = i;
|
||||
found_free_channel = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_free_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* To select a pin for any of the eight pin interrupts, write the pin number
|
||||
* as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55.
|
||||
* @see: mbed_capi/PinNames.h
|
||||
*/
|
||||
if (pin <16) {
|
||||
CMSDK_GPIO_0->INTENSET |= (0x1 << pin);
|
||||
}
|
||||
|
||||
if (pin >= 16) {
|
||||
CMSDK_GPIO_1->INTENSET |= (0x1 << pin);
|
||||
}
|
||||
|
||||
void (*channels_irq)(void) = NULL;
|
||||
switch (obj->ch) {
|
||||
case 0:
|
||||
channels_irq = &gpio0_irq0;
|
||||
break;
|
||||
case 1:
|
||||
channels_irq = &gpio0_irq1;
|
||||
break;
|
||||
case 2:
|
||||
channels_irq = &gpio0_irq2;
|
||||
break;
|
||||
case 3:
|
||||
channels_irq = &gpio0_irq3;
|
||||
break;
|
||||
case 4:
|
||||
channels_irq = &gpio0_irq4;
|
||||
break;
|
||||
case 5:
|
||||
channels_irq = &gpio0_irq5;
|
||||
break;
|
||||
case 6:
|
||||
channels_irq = &gpio0_irq6;
|
||||
break;
|
||||
case 7:
|
||||
channels_irq = &gpio0_irq7;
|
||||
break;
|
||||
case 8:
|
||||
channels_irq = &gpio0_irq8;
|
||||
break;
|
||||
case 9:
|
||||
channels_irq = &gpio0_irq9;
|
||||
break;
|
||||
case 10:
|
||||
channels_irq = &gpio0_irq10;
|
||||
break;
|
||||
case 11:
|
||||
channels_irq = &gpio0_irq11;
|
||||
break;
|
||||
case 12:
|
||||
channels_irq = &gpio0_irq12;
|
||||
break;
|
||||
case 13:
|
||||
channels_irq = &gpio0_irq13;
|
||||
break;
|
||||
case 14:
|
||||
channels_irq = &gpio0_irq14;
|
||||
break;
|
||||
case 15:
|
||||
channels_irq = &gpio0_irq15;
|
||||
break;
|
||||
case 16:
|
||||
channels_irq = &gpio1_irq0;
|
||||
break;
|
||||
case 17:
|
||||
channels_irq = &gpio1_irq1;
|
||||
break;
|
||||
case 18:
|
||||
channels_irq = &gpio1_irq2;
|
||||
break;
|
||||
case 19:
|
||||
channels_irq = &gpio1_irq3;
|
||||
break;
|
||||
case 20:
|
||||
channels_irq = &gpio1_irq4;
|
||||
break;
|
||||
case 21:
|
||||
channels_irq = &gpio1_irq5;
|
||||
break;
|
||||
case 22:
|
||||
channels_irq = &gpio1_irq6;
|
||||
break;
|
||||
case 23:
|
||||
channels_irq = &gpio1_irq7;
|
||||
break;
|
||||
case 24:
|
||||
channels_irq = &gpio1_irq8;
|
||||
break;
|
||||
case 25:
|
||||
channels_irq = &gpio1_irq9;
|
||||
break;
|
||||
case 26:
|
||||
channels_irq = &gpio1_irq10;
|
||||
break;
|
||||
case 27:
|
||||
channels_irq = &gpio1_irq11;
|
||||
break;
|
||||
case 28:
|
||||
channels_irq = &gpio1_irq12;
|
||||
break;
|
||||
case 29:
|
||||
channels_irq = &gpio1_irq13;
|
||||
break;
|
||||
case 30:
|
||||
channels_irq = &gpio1_irq14;
|
||||
break;
|
||||
case 31:
|
||||
channels_irq = &gpio1_irq15;
|
||||
break;
|
||||
}
|
||||
|
||||
NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch), (uint32_t)channels_irq);
|
||||
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_irq_free(gpio_irq_t *obj)
|
||||
{
|
||||
channel_ids[obj->ch] = 0;
|
||||
/* Not implemented because the device can not be uninitialized. */
|
||||
}
|
||||
|
||||
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||
{
|
||||
unsigned int ch_bit = (1 << obj->ch);
|
||||
/* Interrupt is set on an input pin on rising or falling edge */
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE | ARM_GPIO_INPUT | ARM_GPIO_IRQ |
|
||||
ARM_GPIO_IRQ_EDGE;
|
||||
|
||||
if (obj->ch <16) {
|
||||
/* Clear interrupt */
|
||||
if (!(CMSDK_GPIO_0->INTTYPESET & ch_bit)) {
|
||||
CMSDK_GPIO_0->INTCLEAR = ch_bit;
|
||||
}
|
||||
CMSDK_GPIO_0->INTTYPESET &= ch_bit;
|
||||
switch (event) {
|
||||
case IRQ_RISE:
|
||||
flags |= ARM_GPIO_IRQ_ACTIVE_HIGH;
|
||||
break;
|
||||
case IRQ_FALL:
|
||||
flags |= ARM_GPIO_IRQ_ACTIVE_LOW;
|
||||
break;
|
||||
case IRQ_NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set interrupt */
|
||||
if (event == IRQ_RISE) {
|
||||
CMSDK_GPIO_0->INTPOLSET |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_0->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTENCLR |= ch_bit;
|
||||
}
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTPOLCLR |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_0->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTENCLR |= ch_bit;
|
||||
}
|
||||
}
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, obj->pin_number,
|
||||
flags);
|
||||
|
||||
/* Record the event type of this pin */
|
||||
gpio_irq[obj->exp_pin_number].event = event;
|
||||
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
|
||||
if (enable) {
|
||||
gpio_irq_enable(obj);
|
||||
} else {
|
||||
/* Clear interrupt */
|
||||
if (!(CMSDK_GPIO_1->INTTYPESET & ch_bit)) {
|
||||
CMSDK_GPIO_1->INTCLEAR = ch_bit;
|
||||
}
|
||||
CMSDK_GPIO_1->INTTYPESET &= ch_bit;
|
||||
|
||||
/* Set interrupt */
|
||||
if (event == IRQ_RISE) {
|
||||
CMSDK_GPIO_1->INTPOLSET |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_1->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTENCLR |= ch_bit;
|
||||
}
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTPOLCLR |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_1->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTENCLR |= ch_bit;
|
||||
}
|
||||
}
|
||||
gpio_irq_disable(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_irq_t *obj)
|
||||
{
|
||||
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
(void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, ARM_GPIO_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_irq_t *obj)
|
||||
{
|
||||
NVIC_DisableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
(void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, ARM_GPIO_IRQ_DISABLE);
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_GPIO_OBJECT_H
|
||||
#define MBED_GPIO_OBJECT_H
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
uint32_t pin_number;
|
||||
__IO uint32_t *reg_dir;
|
||||
__IO uint32_t *reg_dirclr;
|
||||
__IO uint32_t *reg_data;
|
||||
__I uint32_t *reg_in;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
if (value) {
|
||||
*obj->reg_data |= (obj->mask);
|
||||
} else {
|
||||
*obj->reg_data &= ~(obj->mask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int gpio_read(gpio_t *obj)
|
||||
{
|
||||
return ((*obj->reg_in & obj->mask) ? 1 : 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MBED_GPIO_OBJECTS_H__
|
||||
#define __MBED_GPIO_OBJECTS_H__
|
||||
|
||||
/*
|
||||
* GPIO device number, there are 16 pins per GPIO
|
||||
* equivalent: pin / 16
|
||||
*/
|
||||
#define GPIO_DEV_NUMBER(pin) ((pin) >> 4)
|
||||
/*
|
||||
* Pin number of this pin inside its GPIO
|
||||
* equivalent: pin % 16
|
||||
*/
|
||||
#define GPIO_PIN_NUMBER(pin) ((pin) & 0xF)
|
||||
|
||||
/* Number of the GPIO device */
|
||||
#define GPIO0_NUMBER 0
|
||||
#define GPIO1_NUMBER 1
|
||||
#define GPIO2_NUMBER 2
|
||||
#define GPIO3_NUMBER 3
|
||||
|
||||
/* Base EXP pin number for the corresponding GPIO */
|
||||
#define EXP_PIN_BASE0 EXP0
|
||||
#define EXP_PIN_BASE1 EXP16
|
||||
#define EXP_PIN_BASE2 EXP32
|
||||
#define EXP_PIN_BASE3 EXP48
|
||||
|
||||
#define GPIO_DEVICES 4
|
||||
#define PINS_PER_GPIO 16
|
||||
/* Pins 4 to 15 of GPIO3 are not used */
|
||||
#define PINS_NOT_USED 12
|
||||
#define PINS_NUMBER (GPIO_DEVICES * PINS_PER_GPIO - PINS_NOT_USED)
|
||||
|
||||
/* GPIO3 port only uses first 4 pins */
|
||||
#define GPIO3_PIN_NUMBER 4
|
||||
|
||||
/* When doing a port access, the pin number argument is useless */
|
||||
#define ARG_NOT_USED 0
|
||||
|
||||
#endif /* __MBED_GPIO_OBJECTS_H__ */
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Low-power elapsed time measure and interval timer in micro-secundum,
|
||||
* servicing \ref lp_ticker_api.h, using CMSDK Timer1 \ref CMSDK_TIMER1_DEV.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "cmsdk_ticker.h"
|
||||
#include "lp_ticker_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
/**
|
||||
* \brief Calculate clocks to us
|
||||
*
|
||||
* \param[in] tick Number of clock ticks
|
||||
*
|
||||
* \return Number of usec, relative to the timer frequency,
|
||||
* that a given ammount of ticks equates to.
|
||||
*/
|
||||
static uint32_t convert_tick_to_us(uint32_t tick)
|
||||
{
|
||||
return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate us to clock ticks
|
||||
*
|
||||
* \param[in] us Time to convert to clock ticks
|
||||
*
|
||||
* \return Number of clock ticks relative to the timer frequency,
|
||||
* that a given period of usec equates to.
|
||||
*/
|
||||
static uint32_t convert_us_to_tick(uint32_t us)
|
||||
{
|
||||
return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
static const struct tick_cfg_t cfg =
|
||||
{
|
||||
.timer_driver = &CMSDK_TIMER1_DEV,
|
||||
.irq_n = TIMER1_IRQn,
|
||||
.interval_callback = &lp_ticker_irq_handler,
|
||||
.convert_tick_to_time = &convert_tick_to_us,
|
||||
.convert_time_to_tick = &convert_us_to_tick
|
||||
};
|
||||
|
||||
static struct tick_data_t data =
|
||||
{
|
||||
.is_initialized = false,
|
||||
.cumulated_time = 0,
|
||||
.max_interval_time = 0,
|
||||
.reload_time = 0,
|
||||
.interval_callback_enabled = false,
|
||||
.previous_cumulated_time = 0,
|
||||
.previous_elapsed = 0
|
||||
};
|
||||
|
||||
static struct tick_drv_data_t timer_data =
|
||||
{
|
||||
.cfg = &cfg,
|
||||
.data = &data
|
||||
};
|
||||
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
cmsdk_ticker_init(&timer_data);
|
||||
}
|
||||
|
||||
uint32_t lp_ticker_read()
|
||||
{
|
||||
return cmsdk_ticker_read(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
|
||||
}
|
||||
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_disable_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_clear_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_fire_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_fire_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void TIMER1_IRQHandler(void)
|
||||
{
|
||||
cmsdk_ticker_irq_handler(&timer_data);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,34 +13,44 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_OBJECTS_H
|
||||
#define MBED_OBJECTS_H
|
||||
#ifndef __MBED_OBJECTS_H__
|
||||
#define __MBED_OBJECTS_H__
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
#include "platform_devices.h"
|
||||
#include "gpio_objects.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct gpio_s {
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
struct arm_mps2_io_dev_t *mps2_io_dev;
|
||||
uint32_t pin_number;
|
||||
PinDirection direction;
|
||||
} gpio_t;
|
||||
|
||||
struct gpio_irq_s {
|
||||
uint32_t ch;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t pin_number; /* Pin number inside the GPIO */
|
||||
uint32_t exp_pin_number; /* Pin number on the expension port */
|
||||
IRQn_Type irq_number; /* IRQ number of the GPIO interrupt of
|
||||
this pin */
|
||||
};
|
||||
|
||||
struct port_s {
|
||||
__IO uint32_t *reg_dir;
|
||||
__IO uint32_t *reg_dirclr;
|
||||
__IO uint32_t *reg_out;
|
||||
__IO uint32_t *reg_in;
|
||||
PortName port;
|
||||
uint32_t mask;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
};
|
||||
|
||||
struct serial_s {
|
||||
CMSDK_UART_TypeDef *uart;
|
||||
int index;
|
||||
struct arm_uart_dev_t *uart;
|
||||
UARTName index;
|
||||
IRQn_Type irq_number; /* IRQ number of the RX interrupt for
|
||||
this UART device */
|
||||
};
|
||||
|
||||
struct i2c_s {
|
||||
|
@ -58,21 +68,15 @@ struct audio_s {
|
|||
};
|
||||
|
||||
struct spi_s {
|
||||
MPS2_SSP_TypeDef *spi;
|
||||
};
|
||||
|
||||
struct clcd_s {
|
||||
MPS2_SSP_TypeDef *clcd;
|
||||
struct spi_pl022_dev_t *spi;
|
||||
};
|
||||
|
||||
struct analogin_s {
|
||||
uint16_t ctrl_register; /* Control bits with the channel identifier */
|
||||
};
|
||||
|
||||
#include "gpio_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* __MBED_OBJECTS_H__ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,40 +16,64 @@
|
|||
#include "mbed_assert.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define GET_GPIO_PIN_POS(pin) (pin & 0x0F) /* pin % 16 */
|
||||
#define GET_GPIO_MAP_NUM(pin) (pin >> 4) /* pin / 16 */
|
||||
#define GPIO_NUM 4
|
||||
|
||||
static CMSDK_GPIO_TypeDef* GPIO_MAP[GPIO_NUM] = {
|
||||
CMSDK_GPIO0,
|
||||
CMSDK_GPIO1,
|
||||
CMSDK_GPIO2,
|
||||
CMSDK_GPIO3
|
||||
};
|
||||
#include "objects.h"
|
||||
|
||||
void pin_function(PinName pin, int function)
|
||||
{
|
||||
CMSDK_GPIO_TypeDef* p_gpio_map = 0;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t flags;
|
||||
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
/* The pin has to be a GPIO pin */
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
if (function == ALTERNATE_FUNC) {
|
||||
p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)];
|
||||
p_gpio_map->ALTFUNCSET = (1 << GET_GPIO_PIN_POS(pin));
|
||||
} else if(function == GPIO_FUNC) {
|
||||
p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)];
|
||||
p_gpio_map->ALTFUNCCLR = (1 << GET_GPIO_PIN_POS(pin));
|
||||
} else {
|
||||
error("Invalid pin_function value %d", function);
|
||||
switch (function) {
|
||||
case ALTERNATE_FUNC:
|
||||
flags = ARM_GPIO_PIN_DISABLE;
|
||||
break;
|
||||
case GPIO_FUNC:
|
||||
flags = ARM_GPIO_PIN_ENABLE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case GPIO0_NUMBER:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case GPIO1_NUMBER:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case GPIO2_NUMBER:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case GPIO3_NUMBER:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d, associated with expansion pin %d, is disabled",
|
||||
pin, GPIO_DEV_NUMBER(pin));
|
||||
return;
|
||||
}
|
||||
|
||||
arm_gpio_init(gpio_dev);
|
||||
(void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
GPIO_PIN_NUMBER(pin), flags);
|
||||
}
|
||||
}
|
||||
|
||||
void pin_mode(PinName pin, PinMode mode)
|
||||
{
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
/* Pin modes configuration is not supported */
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,86 +13,90 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "port_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "gpio_api.h"
|
||||
|
||||
#define MAX_GPIO_PINS 16
|
||||
#include "objects.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
PinName port_pin(PortName port, int pin_n)
|
||||
{
|
||||
if (pin_n < 0 || pin_n > MAX_GPIO_PINS) {
|
||||
error("Invalid GPIO pin number %d", pin_n);
|
||||
if (pin_n < 0 || pin_n >= PINS_PER_GPIO ||
|
||||
((port == Port3) && (pin_n >= GPIO3_PIN_NUMBER))) {
|
||||
return NC;
|
||||
}
|
||||
|
||||
return (PinName)((port << PORT_SHIFT) | pin_n);
|
||||
return (PINS_PER_GPIO * port + pin_n);
|
||||
}
|
||||
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
|
||||
{
|
||||
uint32_t i;
|
||||
CMSDK_GPIO_TypeDef *port_reg;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE;
|
||||
|
||||
switch (port) {
|
||||
case Port0:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO0_BASE);
|
||||
break;
|
||||
case Port1:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO1_BASE);
|
||||
break;
|
||||
case Port2:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO2_BASE);
|
||||
break;
|
||||
case Port3:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO3_BASE);
|
||||
break;
|
||||
#ifdef ARM_GPIO0
|
||||
case Port0:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case Port1:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case Port2:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case Port3:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("Port%d is not enabled", port);
|
||||
return;
|
||||
}
|
||||
|
||||
obj->port = port;
|
||||
obj->mask = mask;
|
||||
obj->reg_in = &port_reg->DATAOUT;
|
||||
obj->reg_dir = &port_reg->OUTENABLESET;
|
||||
obj->reg_dirclr = &port_reg->OUTENABLECLR;
|
||||
arm_gpio_init(gpio_dev);
|
||||
obj->gpio_dev = gpio_dev;
|
||||
|
||||
/* The function is set per pin: reuse gpio logic */
|
||||
for (i=0; i < MAX_GPIO_PINS; i++) {
|
||||
if (obj->mask & (1<<i)) {
|
||||
gpio_set(port_pin(obj->port, i));
|
||||
}
|
||||
arm_gpio_set_port_mask(gpio_dev, mask);
|
||||
|
||||
switch (dir) {
|
||||
case PIN_INPUT:
|
||||
flags |= ARM_GPIO_INPUT;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
flags |= ARM_GPIO_OUTPUT;
|
||||
break;
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
port_dir(obj, dir);
|
||||
(void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, flags);
|
||||
}
|
||||
|
||||
void port_mode(port_t *obj, PinMode mode)
|
||||
{
|
||||
uint32_t i;
|
||||
/* The mode is set per pin: reuse pinmap logic */
|
||||
for (i=0; i < MAX_GPIO_PINS; i++) {
|
||||
if (obj->mask & (1 << i)) {
|
||||
pin_mode(port_pin(obj->port, i), mode);
|
||||
}
|
||||
}
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
||||
void port_dir(port_t *obj, PinDirection dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case PIN_INPUT:
|
||||
*obj->reg_dir &= ~obj->mask;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
*obj->reg_dir |= obj->mask;
|
||||
break;
|
||||
}
|
||||
uint32_t flags = (dir == PIN_OUTPUT) ? ARM_GPIO_OUTPUT : ARM_GPIO_INPUT;
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
flags);
|
||||
}
|
||||
|
||||
void port_write(port_t *obj, int value)
|
||||
{
|
||||
*obj->reg_in = value;
|
||||
(void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
(uint32_t)value);
|
||||
}
|
||||
|
||||
int port_read(port_t *obj)
|
||||
{
|
||||
return (*obj->reg_in);
|
||||
return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PORT,
|
||||
ARG_NOT_USED);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,174 +20,138 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "serial_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "gpio_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
/******************************************************************************
|
||||
* INITIALIZATION
|
||||
******************************************************************************/
|
||||
|
||||
#define STDIO_UART_NOT_INITED 0
|
||||
#define STDIO_UART_INITED 1
|
||||
#define UART_NUMBER 5
|
||||
|
||||
struct uart_irq_t {
|
||||
uart_irq_handler handler;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_TX[] = {
|
||||
{MCC_TX , UART_0, 0},
|
||||
{USBTX , UART_1, 0},
|
||||
{SH0_TX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_TX, UART_0, 0},
|
||||
{USBTX, UART_1, 0},
|
||||
{SH0_TX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_RX[] = {
|
||||
{MCC_RX , UART_0, 0},
|
||||
{USBRX , UART_1, 0},
|
||||
{SH0_RX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_RX, UART_0, 0},
|
||||
{USBRX, UART_1, 0},
|
||||
{SH0_RX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
#define UART_NUM 5
|
||||
/* Handlers registered */
|
||||
static struct uart_irq_t uart_irq[UART_NUMBER];
|
||||
|
||||
static uart_irq_handler irq_handler;
|
||||
|
||||
int stdio_uart_inited = 0;
|
||||
/* Global variables needed for mbed */
|
||||
int stdio_uart_inited = STDIO_UART_NOT_INITED;
|
||||
serial_t stdio_uart;
|
||||
|
||||
struct serial_global_data_s {
|
||||
uint32_t serial_irq_id;
|
||||
gpio_t sw_rts, sw_cts;
|
||||
uint8_t count, rx_irq_set_flow, rx_irq_set_api;
|
||||
};
|
||||
/*
|
||||
* Fill the serial_obj structure with good elements.
|
||||
*/
|
||||
static uint32_t fill_serial_object(struct serial_s *serial_obj, PinName tx,
|
||||
PinName rx)
|
||||
{
|
||||
UARTName uart_peripheral;
|
||||
|
||||
static struct serial_global_data_s uart_data[UART_NUM];
|
||||
if (serial_obj == NULL) {
|
||||
error("serial_s structure is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uart_peripheral = pinmap_merge(pinmap_peripheral(tx, PinMap_UART_TX),
|
||||
pinmap_peripheral(rx, PinMap_UART_RX));
|
||||
|
||||
switch (uart_peripheral) {
|
||||
#ifdef ARM_UART0
|
||||
case UART_0:
|
||||
serial_obj->uart = &ARM_UART0_DEV;
|
||||
serial_obj->index = UART_0;
|
||||
serial_obj->irq_number = UART0_IRQn;
|
||||
/* Fill stdio_uart global variable with these settings */
|
||||
memcpy(&stdio_uart, serial_obj, sizeof(struct serial_s));
|
||||
stdio_uart_inited = STDIO_UART_INITED;
|
||||
return 0;
|
||||
#endif /* ARM_UART0 */
|
||||
#ifdef ARM_UART1
|
||||
case UART_1:
|
||||
serial_obj->uart = &ARM_UART1_DEV;
|
||||
serial_obj->index = UART_1;
|
||||
serial_obj->irq_number = UART1_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART1 */
|
||||
#ifdef ARM_UART2
|
||||
case UART_2:
|
||||
serial_obj->uart = &ARM_UART2_DEV;
|
||||
serial_obj->index = UART_2;
|
||||
serial_obj->irq_number = UART2_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART2 */
|
||||
#ifdef ARM_UART3
|
||||
case UART_3:
|
||||
serial_obj->uart = &ARM_UART3_DEV;
|
||||
serial_obj->index = UART_3;
|
||||
serial_obj->irq_number = UART3_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART3 */
|
||||
#ifdef ARM_UART4
|
||||
case UART_4:
|
||||
serial_obj->uart = &ARM_UART4_DEV;
|
||||
serial_obj->index = UART_4;
|
||||
serial_obj->irq_number = UART4_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART4 */
|
||||
default:
|
||||
error("can not assign a valid UART peripheral to TX and RX pins given");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
{
|
||||
uint32_t uart_ctrl = 0;
|
||||
|
||||
/* Determine the UART to use */
|
||||
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
||||
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
|
||||
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
|
||||
|
||||
if ((int)uart == NC) {
|
||||
error("Serial pinout mapping failed");
|
||||
if (fill_serial_object(obj, tx, rx) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj->uart = (CMSDK_UART_TypeDef *)uart;
|
||||
|
||||
if (tx != NC) {
|
||||
uart_ctrl = 0x01; /* TX enable */
|
||||
}
|
||||
if (rx != NC) {
|
||||
uart_ctrl |= 0x02; /* RX enable */
|
||||
}
|
||||
|
||||
switch (uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->CTRL = uart_ctrl;
|
||||
obj->index = 0;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->CTRL = uart_ctrl;
|
||||
obj->index = 1;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->CTRL = 0;
|
||||
obj->index = 2;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART2->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->CTRL = 0;
|
||||
obj->index = 3;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART3->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->CTRL = 0;
|
||||
obj->index = 4;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART4->CTRL = uart_ctrl;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set default baud rate and format */
|
||||
serial_baud(obj, 9600);
|
||||
(void)arm_uart_init(obj->uart, SystemCoreClock);
|
||||
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
* Ref. DDI0479C_cortex_m_system_design_kit_r1p0_trm.pdf
|
||||
* If tx and rx pins are not linked to a GPIO (like for UART0),
|
||||
* pin_function will have no effect.
|
||||
*/
|
||||
uart_data[obj->index].sw_rts.pin = NC;
|
||||
uart_data[obj->index].sw_cts.pin = NC;
|
||||
|
||||
if (uart == STDIO_UART) {
|
||||
stdio_uart_inited = 1;
|
||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
||||
}
|
||||
|
||||
/* Clear UART */
|
||||
serial_clear(obj);
|
||||
pin_function(tx, pinmap_function(tx, PinMap_UART_TX));
|
||||
pin_function(rx, pinmap_function(rx, PinMap_UART_RX));
|
||||
}
|
||||
|
||||
void serial_free(serial_t *obj)
|
||||
{
|
||||
uart_data[obj->index].serial_irq_id = 0;
|
||||
uart_irq[obj->index].id = 0;
|
||||
uart_irq[obj->index].handler = 0;
|
||||
}
|
||||
|
||||
void serial_baud(serial_t *obj, int baudrate)
|
||||
{
|
||||
/*
|
||||
* The MPS2 has a simple divider to control the baud rate.
|
||||
* The formula is:
|
||||
* Baudrate = PCLK / BAUDDIV where PCLK = SystemCoreClock and
|
||||
* BAUDDIV is the desire baudrate
|
||||
*
|
||||
* So, if the desired baud rate is 9600 the calculation will be:
|
||||
* Baudrate = SystemCoreClock / 9600;
|
||||
*/
|
||||
|
||||
/* Check to see if minimum baud value entered */
|
||||
int baudrate_div = 0;
|
||||
|
||||
if (baudrate == 0) {
|
||||
error("Invalid baudrate value");
|
||||
return;
|
||||
if (arm_uart_set_baudrate(obj->uart, (uint32_t)baudrate) !=
|
||||
ARM_UART_ERR_NONE) {
|
||||
error("Invalid baudrate value or uart not initialized");
|
||||
}
|
||||
|
||||
baudrate_div = SystemCoreClock / baudrate;
|
||||
|
||||
if (baudrate >= 16) {
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
default:
|
||||
error("Invalid uart object");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error("Invalid baudrate value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void serial_format(serial_t *obj, int data_bits,
|
||||
|
@ -204,138 +168,160 @@ void serial_format(serial_t *obj, int data_bits,
|
|||
/******************************************************************************
|
||||
* INTERRUPTS HANDLING
|
||||
******************************************************************************/
|
||||
static inline void uart_irq(uint32_t intstatus, uint32_t index,
|
||||
CMSDK_UART_TypeDef *puart)
|
||||
#ifdef ARM_UART0
|
||||
void UART0_IRQHandler()
|
||||
{
|
||||
SerialIrq irq_type;
|
||||
|
||||
switch (intstatus) {
|
||||
case 1:
|
||||
irq_type = TxIrq;
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART0_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART0_DEV, irq);
|
||||
if(uart_irq[UART_0].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
break;
|
||||
case 2:
|
||||
irq_type = RxIrq;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
|
||||
gpio_write(&uart_data[index].sw_rts, 1);
|
||||
/* Disable interrupt if it wasn't enabled by the application */
|
||||
if (!uart_data[index].rx_irq_set_api) {
|
||||
/* Disable Rx interrupt */
|
||||
puart->CTRL &= ~(CMSDK_UART_CTRL_RXIRQEN_Msk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
if (uart_data[index].serial_irq_id != 0) {
|
||||
if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api)) {
|
||||
irq_handler(uart_data[index].serial_irq_id, irq_type);
|
||||
#ifdef ARM_UART1
|
||||
void UART1_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART1_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART1_DEV, irq);
|
||||
if(uart_irq[UART_1].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
if (irq_type == TxIrq) {
|
||||
/* Clear the TX interrupt Flag */
|
||||
puart->INTCLEAR |= 0x01;
|
||||
} else {
|
||||
/* Clear the Rx interupt Flag */
|
||||
puart->INTCLEAR |= 0x02;
|
||||
#ifdef ARM_UART2
|
||||
void UART2_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART2_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART2_DEV, irq);
|
||||
if(uart_irq[UART_2].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
void uart0_irq()
|
||||
#ifdef ARM_UART3
|
||||
void UART3_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART0->INTSTATUS & 0x3, 0, (CMSDK_UART_TypeDef*)CMSDK_UART0);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART3_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART3_DEV, irq);
|
||||
if(uart_irq[UART_3].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
void uart1_irq()
|
||||
#ifdef ARM_UART4
|
||||
void UART4_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART1->INTSTATUS & 0x3, 1, (CMSDK_UART_TypeDef*)CMSDK_UART1);
|
||||
}
|
||||
|
||||
void uart2_irq()
|
||||
{
|
||||
uart_irq(CMSDK_UART2->INTSTATUS & 0x3, 2, (CMSDK_UART_TypeDef*)CMSDK_UART2);
|
||||
}
|
||||
|
||||
void uart3_irq() {
|
||||
uart_irq(CMSDK_UART3->INTSTATUS & 0x3, 3, (CMSDK_UART_TypeDef*)CMSDK_UART3);
|
||||
}
|
||||
|
||||
void uart4_irq() {
|
||||
uart_irq(CMSDK_UART4->INTSTATUS & 0x3, 4, (CMSDK_UART_TypeDef*)CMSDK_UART4);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART4_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART4_DEV, irq);
|
||||
if(uart_irq[UART_4].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART4 */
|
||||
|
||||
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
|
||||
{
|
||||
irq_handler = handler;
|
||||
uart_data[obj->index].serial_irq_id = id;
|
||||
}
|
||||
|
||||
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
|
||||
IRQn_Type irq_n = (IRQn_Type)0;
|
||||
uint32_t vector = 0;
|
||||
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
irq_n = UART0_IRQn;
|
||||
vector = (uint32_t)&uart0_irq;
|
||||
break;
|
||||
case UART_1:
|
||||
irq_n = UART1_IRQn;
|
||||
vector = (uint32_t)&uart1_irq;
|
||||
break;
|
||||
case UART_2:
|
||||
irq_n = UART2_IRQn;
|
||||
vector = (uint32_t)&uart2_irq;
|
||||
break;
|
||||
case UART_3:
|
||||
irq_n = UART3_IRQn;
|
||||
vector = (uint32_t)&uart3_irq;
|
||||
break;
|
||||
case UART_4:
|
||||
irq_n = UART4_IRQn;
|
||||
vector = (uint32_t)&uart4_irq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (irq == TxIrq) {
|
||||
/* Set TX interrupt enable in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_TXIRQEN_Msk;
|
||||
} else {
|
||||
/* Set Rx interrupt on in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_RXIRQEN_Msk;
|
||||
}
|
||||
NVIC_SetVector(irq_n, vector);
|
||||
NVIC_EnableIRQ(irq_n);
|
||||
} else if ((irq == TxIrq) ||
|
||||
(uart_data[obj->index].rx_irq_set_api
|
||||
+ uart_data[obj->index].rx_irq_set_flow == 0)) {
|
||||
/* Disable IRQ */
|
||||
int all_disabled = 0;
|
||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
||||
|
||||
obj->uart->CTRL &= ~(1 << (irq + 2));
|
||||
|
||||
all_disabled = (obj->uart->CTRL & (1 << (other_irq + 2))) == 0;
|
||||
|
||||
if (all_disabled) {
|
||||
NVIC_DisableIRQ(irq_n);
|
||||
}
|
||||
}
|
||||
uart_irq[obj->index].handler = handler;
|
||||
uart_irq[obj->index].id = id;
|
||||
}
|
||||
|
||||
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
if (RxIrq == irq) {
|
||||
uart_data[obj->index].rx_irq_set_api = enable;
|
||||
switch (irq) {
|
||||
case RxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_rx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_rx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
case TxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_tx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_tx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
serial_irq_set_internal(obj, irq, enable);
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -343,34 +329,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
|||
******************************************************************************/
|
||||
int serial_getc(serial_t *obj)
|
||||
{
|
||||
while (serial_readable(obj) == 0) {
|
||||
/* NOP */
|
||||
}
|
||||
uint8_t byte = 0;
|
||||
|
||||
return obj->uart->DATA;
|
||||
while (!serial_readable(obj)){};
|
||||
(void)arm_uart_read(obj->uart, &byte);
|
||||
|
||||
return (int)byte;
|
||||
}
|
||||
|
||||
void serial_putc(serial_t *obj, int c)
|
||||
{
|
||||
while (serial_writable(obj)) {
|
||||
/* NOP */
|
||||
}
|
||||
obj->uart->DATA = c;
|
||||
while (!serial_writable(obj)){};
|
||||
(void)arm_uart_write(obj->uart, (int)c);
|
||||
}
|
||||
|
||||
int serial_readable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x2;
|
||||
return arm_uart_rx_ready(obj->uart);
|
||||
}
|
||||
|
||||
int serial_writable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x1;
|
||||
return arm_uart_tx_ready(obj->uart);
|
||||
}
|
||||
|
||||
void serial_clear(serial_t *obj)
|
||||
{
|
||||
obj->uart->DATA = 0x00;
|
||||
(void)arm_uart_write(obj->uart, 0x00);
|
||||
}
|
||||
|
||||
void serial_pinout_tx(PinName tx)
|
||||
|
@ -395,7 +380,8 @@ void serial_break_clear(serial_t *obj)
|
|||
*/
|
||||
error("serial_break_clear function not supported");
|
||||
}
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow,
|
||||
PinName txflow)
|
||||
{
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,282 +13,253 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <math.h>
|
||||
|
||||
#include "spi_api.h"
|
||||
#include "spi_def.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
|
||||
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
|
||||
#define SPI_PL022_MAX_SRC_VALUE 255
|
||||
#define SPI_PL022_SSPCR0_SCR_POS 8
|
||||
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
static const PinMap PinMap_SPI_SCLK[] = {
|
||||
{SPI_SCLK , SPI_0, 0},
|
||||
{CLCD_SCLK , SPI_1, 0},
|
||||
{ADC_SCLK , SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_SCK , SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_SCK , SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{SPI_SCLK, SPI_0, 0},
|
||||
{CLCD_SCLK, SPI_1, 0},
|
||||
{ADC_SCLK, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_SCK, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_SCK, SPI_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_MOSI[] = {
|
||||
{SPI_MOSI , SPI_0, 0},
|
||||
{CLCD_MOSI , SPI_1, 0},
|
||||
{ADC_MOSI , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_MOSI, SPI_0, 0},
|
||||
{CLCD_MOSI, SPI_1, 0},
|
||||
{ADC_MOSI, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_MOSI, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_MOSI, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_MISO[] = {
|
||||
{SPI_MISO , SPI_0, 0},
|
||||
{CLCD_MISO , SPI_1, 0},
|
||||
{ADC_MISO , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_MISO, SPI_0, 0},
|
||||
{CLCD_MISO, SPI_1, 0},
|
||||
{ADC_MISO, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_MISO, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_MISO, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_SSEL[] = {
|
||||
{SPI_SSEL , SPI_0, 0},
|
||||
{CLCD_SSEL , SPI_1, 0},
|
||||
{ADC_SSEL , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_SSEL, SPI_0, 0},
|
||||
{CLCD_SSEL, SPI_1, 0},
|
||||
{ADC_SSEL, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_nCS, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_nCS, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static inline int ssp_disable(spi_t *obj);
|
||||
static inline int ssp_enable(spi_t *obj);
|
||||
/* SPI configuration values */
|
||||
#define SPI_BITS_MIN_VALUE 4
|
||||
#define SPI_BITS_MAX_VALUE 16
|
||||
#define SPI_MODE_PHASE_BIT 0
|
||||
#define SPI_MODE_PHASE_BIT_MSK (0x1ul << SPI_MODE_PHASE_BIT)
|
||||
#define SPI_MODE_POLARITY_BIT 1
|
||||
#define SPI_MODE_POLARITY_BIT_MSK (0x1ul << SPI_MODE_POLARITY_BIT)
|
||||
#define SPI_MODE_MAX_VALUE_MSK ((0x1ul << (SPI_MODE_POLARITY_BIT+1))-1)
|
||||
|
||||
static uint32_t spi_fill_object(spi_t *obj, PinName mosi, PinName miso,
|
||||
PinName sclk, PinName ssel)
|
||||
{
|
||||
/* Determine the SPI to use */
|
||||
uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
|
||||
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
|
||||
uint32_t spi_index = pinmap_merge(spi_data, spi_cntl);
|
||||
if ((spi_data == (uint32_t)NC) || (spi_index == (uint32_t)NC)) {
|
||||
/* Both miso and mosi or all 4 pins are NC */
|
||||
error("SPI pinout mapping failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (spi_index) {
|
||||
#ifdef ARM_SPI0
|
||||
case SPI_0:
|
||||
obj->spi = &SPI0_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI0 */
|
||||
#ifdef ARM_SPI1
|
||||
case SPI_1:
|
||||
obj->spi = &SPI1_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI1 */
|
||||
#ifdef ARM_SPI2
|
||||
case SPI_2:
|
||||
obj->spi = &SPI2_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI2 */
|
||||
#ifdef ARM_SPI3
|
||||
case SPI_3:
|
||||
obj->spi = &SPI3_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI3 */
|
||||
#ifdef ARM_SPI4
|
||||
case SPI_4:
|
||||
obj->spi = &SPI4_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI4 */
|
||||
default:
|
||||
error("Can not assign valid SPI peripheral to the pins given");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
||||
{
|
||||
/* Determine the SPI to use */
|
||||
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
||||
|
||||
obj->spi = (MPS2_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
|
||||
if ((int)obj->spi == NC) {
|
||||
error("SPI pinout mapping failed");
|
||||
if (spi_fill_object(obj, mosi, miso, sclk, ssel) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable power and clocking */
|
||||
switch ((int)obj->spi) {
|
||||
case SPI_0:
|
||||
obj->spi->CR1 = 0;
|
||||
obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
|
||||
obj->spi->CPSR = SSP_CPSR_DFLT;
|
||||
obj->spi->IMSC = 0x8;
|
||||
obj->spi->DMACR = 0;
|
||||
obj->spi->CR1 = SSP_CR1_SSE_Msk;
|
||||
obj->spi->ICR = 0x3;
|
||||
break;
|
||||
case SPI_1: /* Configure SSP used for LCD */
|
||||
obj->spi->CR1 = 0; /* Synchronous serial port disable */
|
||||
obj->spi->DMACR = 0; /* Disable FIFO DMA */
|
||||
obj->spi->IMSC = 0; /* Mask all FIFO/IRQ interrupts */
|
||||
obj->spi->ICR = ((1ul << 0) | /* Clear SSPRORINTR interrupt */
|
||||
(1ul << 1) ); /* Clear SSPRTINTR interrupt */
|
||||
obj->spi->CR0 = ((7ul << 0) | /* 8 bit data size */
|
||||
(0ul << 4) | /* Motorola frame format */
|
||||
(0ul << 6) | /* CPOL = 0 */
|
||||
(0ul << 7) | /* CPHA = 0 */
|
||||
(1ul << 8) ); /* Set serial clock rate */
|
||||
obj->spi->CPSR = (2ul << 0); /* set SSP clk to 6MHz (6.6MHz max) */
|
||||
obj->spi->CR1 = ((1ul << 1) | /* Synchronous serial port enable */
|
||||
(0ul << 2) ); /* Device configured as master */
|
||||
break;
|
||||
case SPI_2: /* Shield ADC SPI */
|
||||
case SPI_3: /* Shield 0 SPI */
|
||||
case SPI_4: /* Shield 1 SPI */
|
||||
obj->spi->CR1 = 0;
|
||||
obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
|
||||
obj->spi->CPSR = SSP_CPSR_DFLT;
|
||||
obj->spi->IMSC = 0x8;
|
||||
obj->spi->DMACR = 0;
|
||||
obj->spi->CR1 = SSP_CR1_SSE_Msk;
|
||||
obj->spi->ICR = 0x3;
|
||||
/* Set pin function as an alt-function */
|
||||
if (mosi != NC) {
|
||||
pin_function(mosi, ALTERNATE_FUNC);
|
||||
}
|
||||
if (miso != NC) {
|
||||
pin_function(miso, ALTERNATE_FUNC);
|
||||
}
|
||||
if (sclk != NC) {
|
||||
pin_function(sclk, ALTERNATE_FUNC);
|
||||
}
|
||||
if (ssel != NC) {
|
||||
pin_function(ssel, ALTERNATE_FUNC);
|
||||
}
|
||||
break;
|
||||
(void)spi_pl022_init(obj->spi, SystemCoreClock);
|
||||
|
||||
/*
|
||||
* If the pins are not linked to a GPIO,
|
||||
* pin_function will have no effect.
|
||||
* Mosi, miso and ssel pins are allowed to be NC,
|
||||
* call pin_function only if they are connected
|
||||
*/
|
||||
if (mosi != NC) {
|
||||
pin_function(mosi, pinmap_function(mosi, PinMap_SPI_MOSI));
|
||||
}
|
||||
|
||||
/* Set default format and frequency */
|
||||
if (ssel == NC) {
|
||||
spi_format(obj, 8, 0, 0); /* 8 bits, mode 0, master */
|
||||
} else {
|
||||
spi_format(obj, 8, 0, 1); /* 8 bits, mode 0, slave */
|
||||
if (miso != NC) {
|
||||
pin_function(miso, pinmap_function(miso, PinMap_SPI_MISO));
|
||||
}
|
||||
|
||||
/* Default SPI frequency */
|
||||
spi_frequency(obj, 1000000);
|
||||
|
||||
/* Enable the ssp channel */
|
||||
ssp_enable(obj);
|
||||
if (ssel != NC) {
|
||||
pin_function(ssel, pinmap_function(ssel, PinMap_SPI_SSEL));
|
||||
}
|
||||
pin_function(sclk, pinmap_function(sclk, PinMap_SPI_SCLK));
|
||||
}
|
||||
|
||||
void spi_free(spi_t *obj)
|
||||
{
|
||||
error("SPI free error");
|
||||
/* No need to implement free function, this API is intentionally blank */
|
||||
}
|
||||
|
||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
||||
{
|
||||
ssp_disable(obj);
|
||||
if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
|
||||
uint32_t polarity, phase, frame_format;
|
||||
struct spi_pl022_ctrl_cfg_t ctrl_cfg;
|
||||
|
||||
if (!(bits >= SPI_BITS_MIN_VALUE && bits <= SPI_BITS_MAX_VALUE) ||
|
||||
(mode & ~SPI_MODE_MAX_VALUE_MSK)) {
|
||||
error("SPI format error");
|
||||
return;
|
||||
}
|
||||
|
||||
int polarity = (mode & 0x2) ? 1 : 0;
|
||||
int phase = (mode & 0x1) ? 1 : 0;
|
||||
spi_pl022_dev_disable(obj->spi);
|
||||
if (spi_pl022_get_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) {
|
||||
error("SPI not initialized");
|
||||
return;
|
||||
};
|
||||
|
||||
// set it up
|
||||
int DSS = bits - 1; /* DSS (data select size) */
|
||||
int SPO = (polarity) ? 1 : 0; /* SPO - clock out polarity */
|
||||
int SPH = (phase) ? 1 : 0; /* SPH - clock out phase */
|
||||
polarity = (mode & SPI_MODE_POLARITY_BIT_MSK) ? 1u : 0;
|
||||
phase = (mode & SPI_MODE_PHASE_BIT_MSK) ? 1u : 0;
|
||||
frame_format = (SPI_PL022_CFG_FRF_MOT << 0 |
|
||||
polarity << 6 |
|
||||
phase << 7);
|
||||
|
||||
int FRF = 0; /* FRF (frame format) = SPI */
|
||||
uint32_t tmp = obj->spi->CR0;
|
||||
tmp &= ~(0xFFFF);
|
||||
tmp |= DSS << 0
|
||||
| FRF << 4
|
||||
| SPO << 6
|
||||
| SPH << 7;
|
||||
obj->spi->CR0 = tmp;
|
||||
ctrl_cfg.frame_format = (uint8_t) frame_format;
|
||||
ctrl_cfg.word_size = (uint8_t) bits;
|
||||
ctrl_cfg.spi_mode =
|
||||
slave ? SPI_PL022_SLAVE_SELECT : SPI_PL022_MASTER_SELECT;
|
||||
|
||||
tmp = obj->spi->CR1;
|
||||
tmp &= ~(0xD);
|
||||
tmp |= 0 << 0 /* LBM - loop back mode - off */
|
||||
| ((slave) ? 1 : 0) << 2 /* MS - master slave mode, 1 = slave */
|
||||
| 0 << 3; /* SOD - slave output disable - na */
|
||||
obj->spi->CR1 = tmp;
|
||||
if (spi_pl022_set_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) {
|
||||
error("SPI configuration failed");
|
||||
}
|
||||
|
||||
ssp_enable(obj);
|
||||
spi_pl022_dev_enable(obj->spi);
|
||||
}
|
||||
|
||||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
uint32_t clkps_dvsr, scr;
|
||||
uint32_t sys_clk = SystemCoreClock;
|
||||
spi_pl022_dev_disable(obj->spi);
|
||||
|
||||
for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE;
|
||||
clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) {
|
||||
|
||||
/* Calculate clock rate based on the new clock prescale divisor */
|
||||
scr = (sys_clk / (clkps_dvsr * hz)) - 1;
|
||||
|
||||
/* Checks if it can be supported by the divider */
|
||||
if (scr <= SPI_PL022_MAX_SRC_VALUE) {
|
||||
ssp_disable(obj);
|
||||
obj->spi->CPSR = clkps_dvsr;
|
||||
obj->spi->CR0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
obj->spi->CR0 |= (scr << SPI_PL022_SSPCR0_SCR_POS);
|
||||
ssp_enable(obj);
|
||||
return;
|
||||
}
|
||||
obj->spi->data->ctrl_cfg.bit_rate = hz;
|
||||
if (spi_pl022_set_sys_clk(obj->spi, SystemCoreClock) != 0) {
|
||||
error("SPI frequency config failed");
|
||||
}
|
||||
|
||||
error("Couldn't setup requested SPI frequency %dHz", hz);
|
||||
}
|
||||
|
||||
static inline int ssp_disable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->CR1 &= ~(1 << 1);
|
||||
}
|
||||
|
||||
static inline int ssp_enable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->CR1 |= SSP_CR1_SSE_Msk;
|
||||
}
|
||||
|
||||
static inline int ssp_readable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->SR & (1 << 2);
|
||||
}
|
||||
|
||||
static inline int ssp_writeable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->SR & SSP_SR_BSY_Msk;
|
||||
}
|
||||
|
||||
static inline void ssp_write(spi_t *obj, int value)
|
||||
{
|
||||
obj->spi->DR = value;
|
||||
while (ssp_writeable(obj));
|
||||
}
|
||||
static inline int ssp_read(spi_t *obj)
|
||||
{
|
||||
int read_DR = obj->spi->DR;
|
||||
return read_DR;
|
||||
}
|
||||
|
||||
static inline int ssp_busy(spi_t *obj)
|
||||
{
|
||||
return (obj->spi->SR & (1 << 4)) ? (1) : (0);
|
||||
spi_pl022_dev_enable(obj->spi);
|
||||
}
|
||||
|
||||
int spi_master_write(spi_t *obj, int value)
|
||||
{
|
||||
ssp_write(obj, value);
|
||||
while (obj->spi->SR & SSP_SR_BSY_Msk); /* Wait for send to finish */
|
||||
return (ssp_read(obj));
|
||||
int32_t rx_data = 0;
|
||||
uint32_t size = 1;
|
||||
|
||||
if(obj->spi->data->ctrl_cfg.word_size > 8) {
|
||||
size = 2;
|
||||
}
|
||||
|
||||
if (spi_pl022_txrx_blocking(obj->spi, &value, &size, &rx_data, &size) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rx_data;
|
||||
}
|
||||
|
||||
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||
char *rx_buffer, int rx_length, char write_fill)
|
||||
{
|
||||
int total = (tx_length > rx_length) ? tx_length : rx_length;
|
||||
char out, in;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
out = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
in = spi_master_write(obj, out);
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = in;
|
||||
}
|
||||
if (spi_pl022_txrx_blocking(obj->spi, tx_buffer, (uint32_t*)&tx_length,
|
||||
rx_buffer, (uint32_t*)&rx_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return total;
|
||||
return ((tx_length > rx_length) ? tx_length : rx_length);
|
||||
}
|
||||
|
||||
int spi_slave_receive(spi_t *obj)
|
||||
{
|
||||
return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
|
||||
int32_t status = spi_pl022_get_status(obj->spi);
|
||||
/* Rx FIFO not empty and device not busy */
|
||||
int32_t ret = ((status & SPI_PL022_SSPSR_RNE_MSK) &&
|
||||
!(status & SPI_PL022_SSPSR_BSY_MSK));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t spi_get_module(spi_t *obj)
|
||||
{
|
||||
if (obj->spi == &SPI0_PL022_DEV) {
|
||||
return SPI_0;
|
||||
} else if (obj->spi == &SPI1_PL022_DEV) {
|
||||
return SPI_1;
|
||||
} else if (obj->spi == &SPI2_PL022_DEV) {
|
||||
return SPI_2;
|
||||
} else if (obj->spi == &SPI3_PL022_DEV) {
|
||||
return SPI_3;
|
||||
} else if (obj->spi == &SPI4_PL022_DEV) {
|
||||
return SPI_4;
|
||||
} else {
|
||||
error("SPI object is not initialized");
|
||||
return (SPI_NC);
|
||||
}
|
||||
}
|
||||
|
||||
int spi_slave_read(spi_t *obj)
|
||||
{
|
||||
return obj->spi->DR;
|
||||
while(spi_slave_receive(obj) == 0) {};
|
||||
return spi_pl022_slave_read(obj->spi);
|
||||
}
|
||||
|
||||
void spi_slave_write(spi_t *obj, int value)
|
||||
{
|
||||
while (ssp_writeable(obj) == 0);
|
||||
obj->spi->DR = value;
|
||||
(void)spi_pl022_write(obj->spi, SPI_PL022_SLAVE_SELECT, &value);
|
||||
}
|
||||
|
||||
int spi_busy(spi_t *obj)
|
||||
{
|
||||
return ssp_busy(obj);
|
||||
int32_t status = spi_pl022_get_status(obj->spi);
|
||||
return (status & SPI_PL022_SSPSR_BSY_MSK);
|
||||
}
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ----------------------------------------------------------------
|
||||
* File: spi_def.h
|
||||
* Release: Version 2.0
|
||||
* ----------------------------------------------------------------
|
||||
*
|
||||
* SSP interface Support
|
||||
* =====================
|
||||
*/
|
||||
|
||||
#define SSPCS_BASE (0x4002804C) // SSP chip select register
|
||||
#define SSP_BASE (0x40020000) // SSP Prime Cell
|
||||
|
||||
#define SSPCR0 ((volatile unsigned int *)(SSP_BASE + 0x00))
|
||||
#define SSPCR1 ((volatile unsigned int *)(SSP_BASE + 0x04))
|
||||
#define SSPDR ((volatile unsigned int *)(SSP_BASE + 0x08))
|
||||
#define SSPSR ((volatile unsigned int *)(SSP_BASE + 0x0C))
|
||||
#define SSPCPSR ((volatile unsigned int *)(SSP_BASE + 0x10))
|
||||
#define SSPIMSC ((volatile unsigned int *)(SSP_BASE + 0x14))
|
||||
#define SSPRIS ((volatile unsigned int *)(SSP_BASE + 0x18))
|
||||
#define SSPMIS ((volatile unsigned int *)(SSP_BASE + 0x1C))
|
||||
#define SSPICR ((volatile unsigned int *)(SSP_BASE + 0x20))
|
||||
#define SSPDMACR ((volatile unsigned int *)(SSP_BASE + 0x24))
|
||||
#define SSPCS ((volatile unsigned int *)(SSPCS_BASE))
|
||||
|
||||
// SSPCR0 Control register 0
|
||||
#define SSPCR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3
|
||||
#define SSPCR0_SPH 0x0080 // SSPCLKOUT phase
|
||||
#define SSPCR0_SPO 0x0040 // SSPCLKOUT polarity
|
||||
#define SSPCR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define SSPCR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define SSPCR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// SSPCR1 Control register 1
|
||||
#define SSPCR1_SOD 0x0008 // Slave Output mode Disable
|
||||
#define SSPCR1_MS 0x0004 // Master or Slave mode
|
||||
#define SSPCR1_SSE 0x0002 // Serial port enable
|
||||
#define SSPCR1_LBM 0x0001 // Loop Back Mode
|
||||
|
||||
// SSPSR Status register
|
||||
#define SSPSR_BSY 0x0010 // Busy
|
||||
#define SSPSR_RFF 0x0008 // Receive FIFO full
|
||||
#define SSPSR_RNE 0x0004 // Receive FIFO not empty
|
||||
#define SSPSR_TNF 0x0002 // Transmit FIFO not full
|
||||
#define SSPSR_TFE 0x0001 // Transmit FIFO empty
|
||||
|
||||
// SSPCPSR Clock prescale register
|
||||
#define SSPCPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8
|
||||
|
||||
// SSPIMSC Interrupt mask set and clear register
|
||||
#define SSPIMSC_TXIM 0x0008 // Transmit FIFO not Masked
|
||||
#define SSPIMSC_RXIM 0x0004 // Receive FIFO not Masked
|
||||
#define SSPIMSC_RTIM 0x0002 // Receive timeout not Masked
|
||||
#define SSPIMSC_RORIM 0x0001 // Receive overrun not Masked
|
||||
|
||||
// SSPRIS Raw interrupt status register
|
||||
#define SSPRIS_TXRIS 0x0008 // Raw Transmit interrupt flag
|
||||
#define SSPRIS_RXRIS 0x0004 // Raw Receive interrupt flag
|
||||
#define SSPRIS_RTRIS 0x0002 // Raw Timemout interrupt flag
|
||||
#define SSPRIS_RORRIS 0x0001 // Raw Overrun interrupt flag
|
||||
|
||||
// SSPMIS Masked interrupt status register
|
||||
#define SSPMIS_TXMIS 0x0008 // Masked Transmit interrupt flag
|
||||
#define SSPMIS_RXMIS 0x0004 // Masked Receive interrupt flag
|
||||
#define SSPMIS_RTMIS 0x0002 // Masked Timemout interrupt flag
|
||||
#define SSPMIS_RORMIS 0x0001 // Masked Overrun interrupt flag
|
||||
|
||||
// SSPICR Interrupt clear register
|
||||
#define SSPICR_RTIC 0x0002 // Clears Timeout interrupt flag
|
||||
#define SSPICR_RORIC 0x0001 // Clears Overrun interrupt flag
|
||||
|
||||
// SSPDMACR DMA control register
|
||||
#define SSPDMACR_TXDMAE 0x0002 // Enable Transmit FIFO DMA
|
||||
#define SSPDMACR_RXDMAE 0x0001 // Enable Receive FIFO DMA
|
||||
|
||||
// SPICS register (0=Chip Select low)
|
||||
#define SSPCS_nCS1 0x0002 // nCS1 (SPI_nSS)
|
||||
|
||||
// SPI defaults
|
||||
#define SSPMAXTIME 1000 // Maximum time to wait for SSP (10*10uS)
|
||||
|
||||
// EEPROM instruction set
|
||||
#define EEWRSR 0x0001 // Write status
|
||||
#define EEWRITE 0x0002 // Write data
|
||||
#define EEREAD 0x0003 // Read data
|
||||
#define EEWDI 0x0004 // Write disable
|
||||
#define EEWREN 0x0006 // Write enable
|
||||
#define EERDSR 0x0005 // Read status
|
||||
|
||||
// EEPROM status register flags
|
||||
#define EERDSR_WIP 0x0001 // Write in process
|
||||
#define EERDSR_WEL 0x0002 // Write enable latch
|
||||
#define EERDSR_BP0 0x0004 // Block protect 0
|
||||
#define EERDSR_BP1 0x0008 // Block protect 1
|
||||
#define EERDSR_WPEN 0x0080 // Write protect enable
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
*
|
||||
* Color LCD Support
|
||||
* =================
|
||||
*/
|
||||
|
||||
// Color LCD Controller Internal Register addresses
|
||||
#define LSSPCS_BASE (0x4002804C) // LSSP chip select register
|
||||
#define LSSP_BASE (0x40021000) // LSSP Prime Cell
|
||||
|
||||
#define LSSPCR0 ((volatile unsigned int *)(LSSP_BASE + 0x00))
|
||||
#define LSSPCR1 ((volatile unsigned int *)(LSSP_BASE + 0x04))
|
||||
#define LSSPDR ((volatile unsigned int *)(LSSP_BASE + 0x08))
|
||||
#define LSSPSR ((volatile unsigned int *)(LSSP_BASE + 0x0C))
|
||||
#define LSSPCPSR ((volatile unsigned int *)(LSSP_BASE + 0x10))
|
||||
#define LSSPIMSC ((volatile unsigned int *)(LSSP_BASE + 0x14))
|
||||
#define LSSPRIS ((volatile unsigned int *)(LSSP_BASE + 0x18))
|
||||
#define LSSPMIS ((volatile unsigned int *)(LSSP_BASE + 0x1C))
|
||||
#define LSSPICR ((volatile unsigned int *)(LSSP_BASE + 0x20))
|
||||
#define LSSPDMACR ((volatile unsigned int *)(LSSP_BASE + 0x24))
|
||||
#define LSSPCS ((volatile unsigned int *)(LSSPCS_BASE))
|
||||
|
||||
// LSSPCR0 Control register 0
|
||||
#define LSSPCR0_SCR_DFLT 0x0100 // Serial Clock Rate (divide), CLK/(CPSR*(1+SCR))
|
||||
#define LSSPCR0_SPH 0x0080 // LSSPCLKOUT phase
|
||||
#define LSSPCR0_SPO 0x0040 // LSSPCLKOUT polarity
|
||||
#define LSSPCR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define LSSPCR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define LSSPCR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// LSSPCR1 Control register 1
|
||||
#define LSSPCR1_SOD 0x0008 // Slave Output mode Disable
|
||||
#define LSSPCR1_MS 0x0004 // Master or Slave mode
|
||||
#define LSSPCR1_SSE 0x0002 // Serial port enable
|
||||
#define LSSPCR1_LBM 0x0001 // Loop Back Mode
|
||||
|
||||
// LSSPSR Status register
|
||||
#define LSSPSR_BSY 0x0010 // Busy
|
||||
#define LSSPSR_RFF 0x0008 // Receive FIFO full
|
||||
#define LSSPSR_RNE 0x0004 // Receive FIFO not empty
|
||||
#define LSSPSR_TNF 0x0002 // Transmit FIFO not full
|
||||
#define LSSPSR_TFE 0x0001 // Transmit FIFO empty
|
||||
|
||||
// LSSPCPSR Clock prescale register
|
||||
#define LSSPCPSR_DFLT 0x0002 // Clock prescale (use with SCR)
|
||||
|
||||
// SPICS register
|
||||
#define LSSPCS_nCS0 0x0001 // nCS0 (CLCD_CS)
|
||||
#define LSSPCS_nCS2 0x0004 // nCS2 (CLCD_T_CS)
|
||||
#define LCD_RESET 0x0008 // RESET (CLCD_RESET)
|
||||
#define LCD_RS 0x0010 // RS (CLCD_RS)
|
||||
#define LCD_RD 0x0020 // RD (CLCD_RD)
|
||||
#define LCD_BL 0x0040 // Backlight (CLCD_BL_CTRL)
|
||||
|
||||
// SPI defaults
|
||||
#define LSSPMAXTIME 10000 // Maximum time to wait for LSSP (10*10uS)
|
||||
#define LSPI_START (0x70) // Start byte for SPI transfer
|
||||
#define LSPI_RD (0x01) // WR bit 1 within start
|
||||
#define LSPI_WR (0x00) // WR bit 0 within start
|
||||
#define LSPI_DATA (0x02) // RS bit 1 within start byte
|
||||
#define LSPI_INDEX (0x00) // RS bit 0 within start byte
|
||||
|
||||
// Screen size
|
||||
#define LCD_WIDTH 320 // Screen Width (in pixels)
|
||||
#define LCD_HEIGHT 240 // Screen Height (in pixels)
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,125 +14,98 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This file is derivative of us_ticker.c from BEETLE */
|
||||
/**
|
||||
* Elapsed time measure and interval timer in micro-secundum,
|
||||
* servicing \ref us_ticker_api.h, using CMSDK Timer0 \ref CMSDK_TIMER0_DEV.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "cmsis.h"
|
||||
#include "cmsdk_ticker.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
#define TIMER_MAX_VALUE 0
|
||||
|
||||
/* Private data */
|
||||
struct us_ticker_drv_data_t {
|
||||
uint32_t inited; /* us ticker initialized */
|
||||
uint32_t overflow_delta; /* us ticker overflow */
|
||||
uint32_t overflow_limit; /* us ticker overflow limit */
|
||||
};
|
||||
|
||||
static struct us_ticker_drv_data_t us_ticker_drv_data = {
|
||||
.inited = 0,
|
||||
.overflow_delta = 0,
|
||||
.overflow_limit = 0
|
||||
};
|
||||
|
||||
|
||||
void __us_ticker_irq_handler(void)
|
||||
/**
|
||||
* \brief Convert clocks to us
|
||||
*
|
||||
* \param[in] tick Number of clocks
|
||||
*
|
||||
* \return Number of usec, relative to the timer frequency,
|
||||
* that a given ammount of ticks equates to.
|
||||
*/
|
||||
static uint32_t convert_tick_to_us(uint32_t tick)
|
||||
{
|
||||
Timer_ClearInterrupt(TIMER1);
|
||||
/*
|
||||
* For each overflow event adds the timer max represented value to
|
||||
* the delta. This allows the us_ticker to keep track of the elapsed
|
||||
* time:
|
||||
* elapsed_time = (num_overflow * overflow_limit) + current_time
|
||||
*/
|
||||
us_ticker_drv_data.overflow_delta += us_ticker_drv_data.overflow_limit;
|
||||
return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert us to clock ticks
|
||||
*
|
||||
* \param[in] us Time to convert to clock ticks
|
||||
*
|
||||
* \return Number of clock ticks relative to the timer frequency,
|
||||
* that a given period of usec equates to.
|
||||
*/
|
||||
static uint32_t convert_us_to_tick(uint32_t us)
|
||||
{
|
||||
return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
static const struct tick_cfg_t cfg =
|
||||
{
|
||||
.timer_driver = &CMSDK_TIMER0_DEV,
|
||||
.irq_n = TIMER0_IRQn,
|
||||
.interval_callback = &us_ticker_irq_handler,
|
||||
.convert_tick_to_time = &convert_tick_to_us,
|
||||
.convert_time_to_tick = &convert_us_to_tick
|
||||
};
|
||||
|
||||
static struct tick_data_t data =
|
||||
{
|
||||
.is_initialized = false,
|
||||
.cumulated_time = 0,
|
||||
.max_interval_time = 0,
|
||||
.reload_time = 0,
|
||||
.interval_callback_enabled = false,
|
||||
.previous_cumulated_time = 0,
|
||||
.previous_elapsed = 0
|
||||
};
|
||||
|
||||
static struct tick_drv_data_t timer_data =
|
||||
{
|
||||
.cfg = &cfg,
|
||||
.data = &data
|
||||
};
|
||||
|
||||
void us_ticker_init(void)
|
||||
{
|
||||
uint32_t us_ticker_irqn0 = 0;
|
||||
uint32_t us_ticker_irqn1 = 0;
|
||||
|
||||
if (us_ticker_drv_data.inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
us_ticker_drv_data.inited = 1;
|
||||
|
||||
/* Initialize Timer 0 */
|
||||
Timer_Initialize(TIMER0, TIMER_MAX_VALUE);
|
||||
/* Enable Timer 0 */
|
||||
Timer_Enable(TIMER0);
|
||||
|
||||
/* Initialize Timer 1 */
|
||||
Timer_Initialize(TIMER1, TIMER_MAX_VALUE);
|
||||
/* Enable Timer 1 */
|
||||
Timer_Enable(TIMER1);
|
||||
|
||||
/* Timer 0 get IRQn */
|
||||
us_ticker_irqn0 = Timer_GetIRQn(TIMER0);
|
||||
NVIC_SetVector((IRQn_Type)us_ticker_irqn0, (uint32_t)us_ticker_irq_handler);
|
||||
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn0);
|
||||
|
||||
/* Timer 1 get IRQn */
|
||||
us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
|
||||
NVIC_SetVector((IRQn_Type)us_ticker_irqn1, (uint32_t)__us_ticker_irq_handler);
|
||||
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn1);
|
||||
|
||||
/* Timer set interrupt on TIMER1 */
|
||||
Timer_SetInterrupt(TIMER1, TIMER_DEFAULT_RELOAD);
|
||||
|
||||
/*
|
||||
* Set us_ticker Overflow limit. The us_ticker overflow limit is required
|
||||
* to calculated the return value of the us_ticker read function in us
|
||||
* on 32bit.
|
||||
* A 32bit us value cannot be represented directly in the Timer Load
|
||||
* register if it is greater than (0xFFFFFFFF ticks)/TIMER_DIVIDER_US.
|
||||
*/
|
||||
us_ticker_drv_data.overflow_limit = Timer_GetReloadValue(TIMER1);
|
||||
cmsdk_ticker_init(&timer_data);
|
||||
}
|
||||
|
||||
uint32_t us_ticker_read()
|
||||
{
|
||||
uint32_t return_value = 0;
|
||||
|
||||
if (!us_ticker_drv_data.inited) {
|
||||
us_ticker_init();
|
||||
}
|
||||
|
||||
return_value = us_ticker_drv_data.overflow_delta + Timer_Read(TIMER1);
|
||||
|
||||
return return_value;
|
||||
return cmsdk_ticker_read(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
uint32_t delta = 0;
|
||||
|
||||
if (!us_ticker_drv_data.inited) {
|
||||
us_ticker_init();
|
||||
}
|
||||
|
||||
delta = timestamp - us_ticker_read();
|
||||
|
||||
/* If the event was not in the past enable interrupt */
|
||||
Timer_SetInterrupt(TIMER0, delta);
|
||||
|
||||
}
|
||||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
|
||||
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
|
||||
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
|
||||
}
|
||||
|
||||
void us_ticker_disable_interrupt(void)
|
||||
{
|
||||
Timer_DisableInterrupt(TIMER0);
|
||||
cmsdk_ticker_disable_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_clear_interrupt(void)
|
||||
{
|
||||
Timer_ClearInterrupt(TIMER0);
|
||||
cmsdk_ticker_clear_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_fire_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void TIMER0_IRQHandler(void)
|
||||
{
|
||||
cmsdk_ticker_irq_handler(&timer_data);
|
||||
}
|
||||
|
|
|
@ -2646,7 +2646,7 @@
|
|||
"supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
|
||||
"extra_labels": ["ARM_SSG", "CM3DS_MPS2"],
|
||||
"macros": ["CMSDK_CM3DS"],
|
||||
"device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC"],
|
||||
"device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC", "LOWPOWERTIMER"],
|
||||
"release_versions": ["2", "5"],
|
||||
"copy_method": "mps2",
|
||||
"reset_method": "reboot.txt"
|
||||
|
|
Loading…
Reference in New Issue