Merge with updated master.

This commit is contained in:
Marco Grella 2015-11-11 13:42:35 +01:00
commit 41f9ca08e2
507 changed files with 63538 additions and 42206 deletions

View file

@ -51,7 +51,6 @@ typedef uint32_t u32_t;
typedef int32_t s32_t;
#define CC_CONF_REGISTER_ARGS 1
#define CC_CONF_FASTCALL __fastcall__
#define ARCH_DOESNT_NEED_ALIGNED_STRUCTS 1

View file

@ -66,9 +66,13 @@ high-level configuration macros may be set:
- Default: 0
- Purpose: Enable UDP support and initialize resolver process on startup.
- WITH_80COL
- Default: 0
- Purpose: Enable 80 column screen.
- WITH_GUI
- Default: 0
- Purpose: Initialize the the CTK process on startup.
- Purpose: Initialize the CTK process on startup.
- WITH_MOUSE
- Default: 0

View file

@ -43,7 +43,7 @@
/*-----------------------------------------------------------------------------------*/
#if LOG_CONF_ENABLED
static char * CC_FASTCALL
static char *
ipaddrtoa(uip_ipaddr_t *ipaddr, char *buffer)
{
char *ptr = buffer;
@ -59,7 +59,7 @@ ipaddrtoa(uip_ipaddr_t *ipaddr, char *buffer)
}
#endif /* LOG_CONF_ENABLED */
/*-----------------------------------------------------------------------------------*/
struct ethernet_config * CC_FASTCALL
struct ethernet_config *
config_read(char *filename)
{
static struct {

View file

@ -35,6 +35,6 @@
#ifndef CONFIG_H_
#define CONFIG_H_
struct ethernet_config * CC_FASTCALL config_read(char *filename);
struct ethernet_config * config_read(char *filename);
#endif /* CONFIG_H_ */

View file

@ -58,7 +58,7 @@ struct {
} *module;
/*---------------------------------------------------------------------------*/
void CC_FASTCALL
void
ethernet_init(struct ethernet_config *config)
{
static const char signature[4] = {0x65, 0x74, 0x68, 0x01};

View file

@ -35,7 +35,7 @@
#ifndef ETHERNET_H_
#define ETHERNET_H_
void CC_FASTCALL ethernet_init(struct ethernet_config *config);
void ethernet_init(struct ethernet_config *config);
uint16_t ethernet_poll(void);
void ethernet_send(void);
void ethernet_exit(void);

View file

@ -139,10 +139,10 @@ ifndef NOAVRSIZE
avr-size -C --mcu=$(MCU) $@
endif
%.hex: %.out
%.hex: %.$(TARGET)
$(OBJCOPY) $^ -j .text -j .data -O ihex $@
%.ihex: %.out
%.ihex: %.$(TARGET)
$(OBJCOPY) $^ -O ihex $@
# Add a namelist to the kernel
@ -160,7 +160,7 @@ endif
#%.hex: %.elf
# $(OBJCOPY) -R .eeprom -R .fuse -R .signature $^ -O ihex $@
%.eep: %.out
%.eep: %.$(TARGET)
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex $^ $@

View file

@ -12,7 +12,6 @@
/* MCUSR is a deprecated name but older avr-libc versions may define it */
#if !defined (MCUCSR)
# if defined (MCUSR)
# warning *** MCUCSR not defined, using MCUSR instead ***
# define MCUCSR MCUSR
# endif
#endif

View file

@ -751,7 +751,8 @@ HAL_RF230_ISR()
#endif
#endif
} else if (interrupt_source & HAL_TRX_END_MASK){
}
if (interrupt_source & HAL_TRX_END_MASK){
INTERRUPTDEBUG(11);
state = hal_subregister_read(SR_TRX_STATUS);
@ -778,16 +779,20 @@ HAL_RF230_ISR()
}
} else if (interrupt_source & HAL_TRX_UR_MASK){
}
if (interrupt_source & HAL_TRX_UR_MASK){
INTERRUPTDEBUG(13);
;
} else if (interrupt_source & HAL_PLL_UNLOCK_MASK){
}
if (interrupt_source & HAL_PLL_UNLOCK_MASK){
INTERRUPTDEBUG(14);
;
} else if (interrupt_source & HAL_PLL_LOCK_MASK){
}
if (interrupt_source & HAL_PLL_LOCK_MASK){
INTERRUPTDEBUG(15);
;
} else if (interrupt_source & HAL_BAT_LOW_MASK){
}
if (interrupt_source & HAL_BAT_LOW_MASK){
/* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */
/* will continously be asserted while the supply voltage is less than the */
/* user-defined voltage threshold. */
@ -796,9 +801,6 @@ HAL_RF230_ISR()
hal_register_write(RG_IRQ_MASK, trx_isr_mask);
INTERRUPTDEBUG(16);
;
} else {
INTERRUPTDEBUG(99);
;
}
}
#endif /* defined(__AVR_ATmega128RFA1__) */

View file

@ -237,6 +237,8 @@ typedef enum{
PROCESS(rf230_process, "RF230 driver");
/*---------------------------------------------------------------------------*/
int rf230_interrupt(void);
static int rf230_on(void);
static int rf230_off(void);
@ -552,7 +554,19 @@ rf230_is_ready_to_send() {
static void
flushrx(void)
{
/* Clear the length field to allow buffering of the next packet */
rxframe[rxframe_head].length=0;
rxframe_head++;
if (rxframe_head >= RF230_CONF_RX_BUFFERS) {
rxframe_head=0;
}
/* If another packet has been buffered, schedule another receive poll */
if (rxframe[rxframe_head].length) {
rf230_interrupt();
}
else {
rf230_pending = 0;
}
}
/*---------------------------------------------------------------------------*/
static void
@ -1434,6 +1448,7 @@ rf230_read(void *buf, unsigned short bufsize)
#if RADIOALWAYSON && DEBUGFLOWSIZE
if (RF230_receive_on==0) {if (debugflow[debugflowsize-1]!='z') DEBUGFLOW('z');} //cxmac calls with radio off?
#endif
flushrx();
return 0;
}
@ -1476,19 +1491,8 @@ rf230_read(void *buf, unsigned short bufsize)
memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
rf230_last_correlation = rxframe[rxframe_head].lqi;
/* Clear the length field to allow buffering of the next packet */
rxframe[rxframe_head].length=0;
rxframe_head++;
if (rxframe_head >= RF230_CONF_RX_BUFFERS) {
rxframe_head=0;
}
/* If another packet has been buffered, schedule another receive poll */
if (rxframe[rxframe_head].length) {
rf230_interrupt();
}
else {
rf230_pending = 0;
}
/* Prepare to receive another packet */
flushrx();
/* Point to the checksum */
framep+=len-AUX_LEN;

View file

@ -67,7 +67,6 @@
/* MCUSR is a deprecated name but older avr-libc versions may define it */
#if !defined (MCUCSR)
# if defined (MCUSR)
# warning *** MCUCSR not defined, using MCUSR instead ***
# define MCUCSR MCUSR
# endif
#endif

View file

@ -38,7 +38,6 @@
#endif
#define CC_CONF_FUNCTION_POINTER_ARGS 1
#define CC_CONF_FASTCALL
#define CC_CONF_VA_ARGS 1
#define CC_CONF_UNSIGNED_CHAR_BUGS 0
#define CC_CONF_REGISTER_ARGS 0

View file

@ -22,6 +22,10 @@ LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch
OBJCOPY_FLAGS += -O binary --gap-fill 0xff
OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb
ifdef WERROR
CFLAGS += -Werror
endif
### Are we building with code size optimisations?
ifeq ($(SMALL),1)
CFLAGS += -Os
@ -51,6 +55,8 @@ CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c
CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ccm.c sha256.c
CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c
CONTIKI_CPU_SOURCEFILES += pka.c bignum-driver.c ecc-driver.c ecc-algorithm.c
CONTIKI_CPU_SOURCEFILES += ecc-curve.c
CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c
CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,462 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Authors: Andreas Dröscher <contiki@anticat.ch>
* Hu Luo
* Hossein Shafagh <shafagh@inf.ethz.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-pka
* @{
*
* \defgroup cc2538-bignum cc2538 BigNum math function driver
*
* Driver for the cc2538 BigNum math functions of the PKC engine
* @{
*
* \file
* Header file for the cc2538 BigNum driver
*
* bignum_subtract_start bignum_subtract_get_result (subtraction)
* bignum_add_start bignum_add_get_result (addition)
* bignum_mod_start bignum_mod_get_result (modulo)
* bignum_exp_mod_start bignum_exp_mod_get_result (modular exponentiation operation)
* bignum_inv_mod_start bignum_inv_mod_get_result (inverse modulo operation)
* bignum_mul_start bignum_mul_get_result (multiplication)
* bignum_divide_start bignum_divide_get_result (division)
* bignum_cmp_start bignum_cmp_get_result (comparison)
*/
#ifndef BIGNUM_DRIVER_H_
#define BIGNUM_DRIVER_H_
#include "contiki.h"
#include "pka.h"
#include <stdint.h>
/** @} */
/*---------------------------------------------------------------------------*/
/** \brief Starts the big number modulus operation.
*
* \param number Pointer to the big number on which modulo operation
* needs to be carried out.
* \param number_size Size of the big number \sa number in 32-bit word.
* \param modulus Pointer to the divisor.
* \param modulus_size Size of the divisor \sa modulus.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the modulo operation on the big num \sa number
* using the divisor \sa modulus. The PKA RAM location where the result
* will be available is stored in \sa result_vector.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of the big number modulus operation.
*
* \param buffer Pointer to buffer where the result needs to
* be stored.
* \param buffer_size Size of the provided buffer in 32 bit size word.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumModStart().
*
* This function gets the result of the big number modulus operation which was
* previously started using the function \sa PKABigNumModStart().
*
* \retval PKA_STATUS_SUCCESS if successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_BUF_UNDERFLOW if the \e size is less than the length
* of the result.
*/
uint8_t bignum_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector);
/** \brief Starts the comparison of two big numbers.
*
* \param number1 Pointer to the first big number.
* \param number2 Pointer to the second big number.
* \param size Size of the big number in 32 bit size word.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the comparison of two big numbers pointed by
* \e number1 and \e number2.
* Note this function expects the size of the two big numbers equal.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_cmp_start(const uint32_t *number1,
const uint32_t *number2,
uint8_t size,
struct process *process);
/** \brief Gets the result of the comparison operation of two big numbers.
*
* This function provides the results of the comparison of two big numbers
* which was started using the \sa PKABigNumCmpStart().
*
* \retval PKA_STATUS_OPERATION_INPRG if the operation is in progress.
* \retval PKA_STATUS_SUCCESS if the two big numbers are equal.
* \retval PKA_STATUS_A_GR_B if the first number is greater than the second.
* \retval PKA_STATUS_A_LT_B if the first number is less than the second.
*/
uint8_t bignum_cmp_get_result(void);
/** \brief Starts the big number inverse modulo operation.
*
* \param number Pointer to the buffer containing the big number
* (dividend).
* \param number_size Size of the \e number in 32 bit word.
* \param modulus Pointer to the buffer containing the modulus.
* \param modulus_size Size of the modulus in 32 bit word.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the the inverse modulo operation on \e number
* using the divisor \e modulus.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_inv_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of the big number inverse modulo operation.
*
* \param buffer Pointer to buffer where the result needs to be
* stored.
* \param buffer_size Size of the provided buffer in 32 bit size
* word.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumInvModStart().
*
* This function gets the result of the big number inverse modulo operation
* previously started using the function \sa PKABigNumInvModStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_BUF_UNDERFLOW if the length of the provided buffer is less
* then the result.
*/
uint8_t bignum_inv_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector);
/** \brief Starts the big number multiplication.
*
* \param multiplicand Pointer to the buffer containing the big
* number multiplicand.
* \param multiplicand_size Size of the multiplicand in 32-bit word.
* \param multiplier Pointer to the buffer containing the big
* number multiplier.
* \param multiplier_size Size of the multiplier in 32-bit word.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the multiplication of the two big numbers.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_mul_start(const uint32_t *multiplicand,
const uint8_t multiplicand_size,
const uint32_t *multiplier,
const uint8_t multiplier_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the results of the big number multiplication.
*
* \param buffer Pointer to buffer where the result needs to be stored.
* \param buffer_size Address of the variable containing the length of the
* buffer. After the operation, the actual length of the resultant is
* stored at this address.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumMultiplyStart().
*
* This function gets the result of the multiplication of two big numbers
* operation previously started using the function \sa
* PKABigNumMultiplyStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
* \retval PKA_STATUS_BUF_UNDERFLOW if the length of the provided buffer is less
* then the length of the result.
*/
uint8_t bignum_mul_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector);
/** \brief Starts the addition of two big number.
*
* \param number1 Pointer to the buffer containing the first big mumber.
* \param number1_size Size of the first big number in 32-bit word.
* \param number2 Pointer to the buffer containing the second big number.
* \param number2_size Size of the second big number in 32-bit word.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the addition of the two big numbers.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_add_start(const uint32_t *number1,
const uint8_t number1_size,
const uint32_t *number2,
const uint8_t number2_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of the addition operation on two big number.
*
* \param buffer Pointer to buffer where the result
* needs to be stored.
* \param buffer_size Address of the variable containing the length of
* the buffer. After the operation the actual length of the
* resultant is stored at this address.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumAddStart().
*
* This function gets the result of the addition operation on two big numbers,
* previously started using the function \sa PKABigNumAddStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
* \retval PKA_STATUS_BUF_UNDERFLOW if the length of the provided buffer is less
* then the length of the result.
*/
uint8_t bignum_add_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector);
/** \brief Starts the substract of two big number.
*
* \param number1 Pointer to the buffer containing the first big mumber.
* \param number1_size Size of the first big number in 32-bit word.
* \param number2 Pointer to the buffer containing the second big number.
* \param number2_size Size of the second big number in 32-bit word.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the substraction of the two big numbers.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_subtract_start(const uint32_t *number1,
const uint8_t number1_size,
const uint32_t *number2,
const uint8_t number2_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of big number subtract.
*
* \param buffer Pointer to store the result of subtraction.
* \param buffer_size Address of the variable containing the length of the
* buffer. After the operation, the actual length of the resultant is
* stored at this address.
* \param result_vector Address of the result location which
* was provided by the start function PKABigNumSubtractStart().
*
* This function gets the result of PKABigNumSubtractStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
*/
uint8_t bignum_subtract_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector);
/** \brief Starts the big number moduluar Exponentiation operation.
*
* \param number Pointer to the Exponent on which moduluar Exponentiation operation
* needs to be carried out.
* \param number_size Size of the the Exponent number number in 32-bit word.
* \param modulus Pointer to the divisor.
* \param modulus_size Size of the divisor modulus.
* \param base Pointer to the Base.
* \param base_size Size of the divisor base.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the moduluar Exponentiation operation on the base num base
* using the Exponent number and the Modulus num modulus. The PKA RAM location where the result
* will be available is stored in \sa result_vector.
* IMPORTANT = Modulus and Based should have buffers of the same length!
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_exp_mod_start(const uint32_t *number,
const uint8_t number_size,
const uint32_t *modulus,
const uint8_t modulus_size,
const uint32_t *base,
const uint8_t base_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of the big number modulus operation result.
*
* \param buffer Pointer to buffer where the result needs to
* be stored.
* \param buffer_size Size of the provided buffer in 32 bit size word.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumExpModStart().
*
* This function gets the result of the big number modulus operation which was
* previously started using the function \sa PKABigNumExpModStart().
*
* \retval PKA_STATUS_SUCCESS if successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_BUF_UNDERFLOW if the \e size is less than the length
* of the result.
*
* \note
* - 0 < number_size <= Max_Len
* - 1 < modulus_size <=Max_Len
* - modulus must be odd and modulus > 232
* - base < modulus
*/
uint8_t bignum_exp_mod_get_result(uint32_t *buffer,
const uint8_t buffer_size,
const uint32_t result_vector);
/** \brief Starts the big number Divide.
*
* \param dividend Pointer to the buffer containing the big
* number dividend.
* \param dividend_size Size of the dividend in 32-bit word.
* \param divisor Pointer to the buffer containing the big
* number divisor.
* \param divisor_size Size of the divisor in 32-bit word.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the divide of the two big numbers.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t bignum_divide_start(const uint32_t *dividend,
const uint8_t dividend_size,
const uint32_t *divisor,
const uint8_t divisor_size,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the results of the big number Divide.
*
* \param buffer Pointer to buffer where the result needs to be stored.
* \param buffer_size Address of the variable containing the length of the
* buffer. After the operation, the actual length of the resultant is
* stored at this address.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKABigNumMultiplyStart().
*
* This function gets the result of the Divide of two big numbers
* operation previously started using the function \sa
* PKABigNumDivideStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
* \retval PKA_STATUS_BUF_UNDERFLOW if the length of the provided buffer is less
* then the length of the result.
*/
uint8_t bignum_divide_get_result(uint32_t *buffer,
uint32_t *buffer_size,
const uint32_t result_vector);
/** @} */
#endif /* BIGNUM_DRIVER_H_ */
/**
* @}
* @}
*/

View file

@ -0,0 +1,200 @@
/*
* Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
* All rights reserved.
*
* Author: Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \addtogroup c2538-ecc-algo
* @{
*
* \file
* Implementation of the cc2538 ECC Algorithms
*/
#include <contiki.h>
#include <process.h>
#include <limits.h>
#include <stdio.h>
#include "ecc-algorithm.h"
#include "ecc-driver.h"
#include "pka.h"
#define CHECK_RESULT(...) \
state->result = __VA_ARGS__; \
if(state->result) { \
printf("Line: %u Error: %u\n", __LINE__, (unsigned int)state->result); \
PT_EXIT(&state->pt); \
}
PT_THREAD(ecc_compare(ecc_compare_state_t *state)) {
PT_BEGIN(&state->pt);
CHECK_RESULT(bignum_cmp_start(state->a, state->b, state->size, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->result = bignum_cmp_get_result();
PT_END(&state->pt);
}
PT_THREAD(ecc_multiply(ecc_multiply_state_t *state)) {
PT_BEGIN(&state->pt);
CHECK_RESULT(ecc_mul_start(state->secret, &state->point_in, state->curve_info, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(ecc_mul_get_result(&state->point_out, state->rv));
PT_END(&state->pt);
}
PT_THREAD(ecc_dsa_sign(ecc_dsa_sign_state_t *state)) {
/* Executed Every Time */
uint8_t size = state->curve_info->size;
const uint32_t *ord = state->curve_info->n;
ec_point_t point;
memcpy(point.x, state->curve_info->x, sizeof(point.x));
memcpy(point.y, state->curve_info->y, sizeof(point.y));
PT_BEGIN(&state->pt);
/* Invert k_e mod n */
CHECK_RESULT(bignum_inv_mod_start(state->k_e, size, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_inv_mod_get_result(state->k_e_inv, size, state->rv));
/* Calculate Point R = K_e * GeneratorPoint */
CHECK_RESULT(ecc_mul_start(state->k_e, &point, state->curve_info, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(ecc_mul_get_result(&state->point_r, state->rv));
/* Calculate signature using big math functions
* d*r (r is the x coordinate of PointR) */
CHECK_RESULT(bignum_mul_start(state->secret, size, state->point_r.x, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->len = 24;
CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
/* d*r mod n */
CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
/* hash + d*r */
CHECK_RESULT(bignum_add_start(state->hash, size, state->signature_s, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->len = 24;
CHECK_RESULT(bignum_add_get_result(state->signature_s, &state->len, state->rv));
/* hash + d*r mod n */
CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
/* k_e_inv * (hash + d*r) */
CHECK_RESULT(bignum_mul_start(state->k_e_inv, size, state->signature_s, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->len = 24;
CHECK_RESULT(bignum_mul_get_result(state->signature_s, &state->len, state->rv));
/* k_e_inv * (hash + d*r) mod n */
CHECK_RESULT(bignum_mod_start(state->signature_s, state->len, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_mod_get_result(state->signature_s, size, state->rv));
PT_END(&state->pt);
}
PT_THREAD(ecc_dsa_verify(ecc_dsa_verify_state_t *state)) {
/* Executed Every Time */
uint8_t size = state->curve_info->size;
const uint32_t *ord = state->curve_info->n;
ec_point_t point;
memcpy(point.x, state->curve_info->x, sizeof(point.x));
memcpy(point.y, state->curve_info->y, sizeof(point.y));
PT_BEGIN(&state->pt);
/* Invert s mod n */
CHECK_RESULT(bignum_inv_mod_start(state->signature_s, size, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_inv_mod_get_result(state->s_inv, size, state->rv));
/* Calculate u1 = s_inv * hash */
CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->hash, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->len = 24;
CHECK_RESULT(bignum_mul_get_result(state->u1, &state->len, state->rv));
/* Calculate u1 = s_inv * hash mod n */
CHECK_RESULT(bignum_mod_start(state->u1, state->len, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_mod_get_result(state->u1, size, state->rv));
/* Calculate u2 = s_inv * r */
CHECK_RESULT(bignum_mul_start(state->s_inv, size, state->signature_r, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->len = 24;
CHECK_RESULT(bignum_mul_get_result(state->u2, &state->len, state->rv));
/* Calculate u2 = s_inv * r mod n */
CHECK_RESULT(bignum_mod_start(state->u2, state->len, ord, size, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(bignum_mod_get_result(state->u2, size, state->rv));
/* Calculate p1 = u1 * A */
CHECK_RESULT(ecc_mul_start(state->u1, &point, state->curve_info, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(ecc_mul_get_result(&state->p1, state->rv));
/* Calculate p2 = u1 * B */
CHECK_RESULT(ecc_mul_start(state->u2, &state->public, state->curve_info, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(ecc_mul_get_result(&state->p2, state->rv));
/* Calculate P = p1 + p2 */
CHECK_RESULT(ecc_add_start(&state->p1, &state->p2, state->curve_info, &state->rv, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
CHECK_RESULT(ecc_add_get_result(&state->p1, state->rv));
/* Verify Result */
CHECK_RESULT(bignum_cmp_start(state->signature_r, state->p1.x, size, state->process));
PT_WAIT_UNTIL(&state->pt, pka_check_status());
state->result = bignum_cmp_get_result();
if((state->result == PKA_STATUS_A_GR_B) || (state->result == PKA_STATUS_A_LT_B)) {
state->result = PKA_STATUS_SIGNATURE_INVALID;
}
PT_END(&state->pt);
}
/**
* @}
* @}
*/

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
* All rights reserved.
*
* Author: Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-ecc
* @{
*
* \defgroup cc2538-ecc-algo cc2538 ECC Algorithms
*
* This is a implementation of ECDH, ECDSA sign and ECDSA verify. It
* uses ecc-driver to communicate with the PKA. It uses continuations
* to free the main CPU / thread while the PKA is calculating.
*
* \note
* Only one request can be processed at a time.
* Maximal supported key length is 384bit (12 words).
* @{
*
* \file
* Header file for the cc2538 ECC Algorithms
*/
#ifndef ECC_ALGORITHM_H_
#define ECC_ALGORITHM_H_
#include "bignum-driver.h"
#include "ecc-driver.h"
typedef struct {
/* Containers for the State */
struct pt pt;
struct process *process;
/* Input Variables */
uint32_t a[12]; /**< Left Number */
uint32_t b[12]; /**< Right Number */
uint8_t size; /**< Length of a and b */
/* Output Variables */
uint8_t result; /**< Result Code */
} ecc_compare_state_t;
/**
* \brief Do a compare of two big numbers
*
* This function can be used for ECDH as well as
* Calculating a Public Key for ECDSA
*/
PT_THREAD(ecc_compare(ecc_compare_state_t *state));
typedef struct {
/* Containers for the State */
struct pt pt;
struct process *process;
/* Input Variables */
ecc_curve_info_t *curve_info; /**< Curve defining the CyclicGroup */
ec_point_t point_in; /**< Generator Point */
uint32_t secret[12]; /**< Secret */
/* Variables Holding intermediate data (initialized/used internally) */
uint32_t rv; /**< Address of Next Result in PKA SRAM */
/* Output Variables */
uint8_t result; /**< Result Code */
ec_point_t point_out; /**< Generated Point */
} ecc_multiply_state_t;
/**
* \brief Do a Multiplication on a EC
*
* This function can be used for ECDH as well as
* Calculating a Public Key for ECDSA
*/
PT_THREAD(ecc_multiply(ecc_multiply_state_t *state));
typedef struct {
/* Containers for the State */
struct pt pt;
struct process *process;
/* Input Variables */
ecc_curve_info_t *curve_info; /**< Curve defining the CyclicGroup */
uint32_t secret[12]; /**< Secret Key */
uint32_t k_e[12]; /**< Ephemeral Key */
uint32_t hash[12]; /**< Hash to be signed */
/* Variables Holding intermediate data (initialized/used internally) */
uint32_t rv; /**< Address of Next Result in PKA SRAM */
uint32_t k_e_inv[12]; /**< Inverted ephemeral Key */
uint32_t len; /**< Length of intermediate Result */
/* Output Variables */
uint8_t result; /**< Result Code */
ec_point_t point_r; /**< Signature R (x coordinate) */
uint32_t signature_s[24]; /**< Signature S */
} ecc_dsa_sign_state_t;
/**
* \brief Sign a Hash
*
* This function has to be called several times until the
* pt state is EXIT
* If the result code is 0 (SUCCESS) the signature can be
* read from point_r and signature_s
*/
PT_THREAD(ecc_dsa_sign(ecc_dsa_sign_state_t *state));
typedef struct {
/* Containers for the State */
struct pt pt;
struct process *process;
/* Input Variables */
ecc_curve_info_t *curve_info; /**< Curve defining the CyclicGroup */
uint32_t signature_r[12]; /**< Signature R */
uint32_t signature_s[12]; /**< Signature S */
uint32_t hash[12]; /**< Hash to be signed */
ec_point_t public; /**< Signature R (x coordinate) */
/* Variables Holding intermediate data (initialized/used internally) */
uint32_t rv; /**< Address of Next Result in PKA SRAM */
uint32_t s_inv[12]; /**< Inverted ephemeral Key */
uint32_t u1[24]; /**< Intermediate result */
uint32_t u2[24]; /**< Intermediate result */
ec_point_t p1; /**< Intermediate result */
ec_point_t p2; /**< Intermediate result */
uint32_t len; /**< Length of intermediate Result */
/* Output Variables */
uint8_t result; /**< Result Code */
} ecc_dsa_verify_state_t;
/**
* \brief Verify Signature
*
* This function has to be called several times until the
* pt state is EXIT
* If the result code is 0 (SUCCESS) the verification
* was success full.
* \note some error codes signal internal errors
* and others signal falls signatures.
*/
PT_THREAD(ecc_dsa_verify(ecc_dsa_verify_state_t *state));
#endif /* ECC_ALGORITHM_H_ */
/**
* @}
* @}
*/

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
* All rights reserved.
*
* Author: Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* \addtogroup c2538-ecc-curves
* @{
*/
#include <contiki.h>
#include <ecc-driver.h>
/* [NIST P-256, X9.62 prime256v1] */
static const uint32_t nist_p_256_p[8] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF };
static const uint32_t nist_p_256_n[8] = { 0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF };
static const uint32_t nist_p_256_a[8] = { 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF };
static const uint32_t nist_p_256_b[8] = { 0x27D2604B, 0x3BCE3C3E, 0xCC53B0F6, 0x651D06B0,
0x769886BC, 0xB3EBBD55, 0xAA3A93E7, 0x5AC635D8 };
static const uint32_t nist_p_256_x[8] = { 0xD898C296, 0xF4A13945, 0x2DEB33A0, 0x77037D81,
0x63A440F2, 0xF8BCE6E5, 0xE12C4247, 0x6B17D1F2 };
static const uint32_t nist_p_256_y[8] = { 0x37BF51F5, 0xCBB64068, 0x6B315ECE, 0x2BCE3357,
0x7C0F9E16, 0x8EE7EB4A, 0xFE1A7F9B, 0x4FE342E2 };
ecc_curve_info_t nist_p_256 = {
.name = "NIST P-256",
.size = 8,
.prime = nist_p_256_p,
.n = nist_p_256_n,
.a = nist_p_256_a,
.b = nist_p_256_b,
.x = nist_p_256_x,
.y = nist_p_256_y
};
/* [NIST P-192, X9.62 prime192v1] */
static const uint32_t nist_p_192_p[6] = { 0xffffffff, 0xffffffff, 0xfffffffe, 0xffffffff,
0xffffffff, 0xffffffff };
static const uint32_t nist_p_192_a[6] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff,
0xffffffff, 0xffffffff };
static const uint32_t nist_p_192_b[6] = { 0xc146b9b1, 0xfeb8deec, 0x72243049, 0x0fa7e9ab,
0xe59c80e7, 0x64210519 };
static const uint32_t nist_p_192_x[6] = { 0x82ff1012, 0xf4ff0afd, 0x43a18800, 0x7cbf20eb,
0xb03090f6, 0x188da80e };
static const uint32_t nist_p_192_y[6] = { 0x1e794811, 0x73f977a1, 0x6b24cdd5, 0x631011ed,
0xffc8da78, 0x07192b95 };
static const uint32_t nist_p_192_n[6] = { 0xb4d22831, 0x146bc9b1, 0x99def836, 0xffffffff,
0xffffffff, 0xffffffff };
ecc_curve_info_t nist_p_192 = {
.name = "NIST P-192",
.size = 6,
.prime = nist_p_192_p,
.n = nist_p_192_n,
.a = nist_p_192_a,
.b = nist_p_192_b,
.x = nist_p_192_x,
.y = nist_p_192_y
};
/**
* @}
* @}
*/

View file

@ -0,0 +1,65 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2014 Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-ecc
* @{
*
* \defgroup cc2538-ecc-curves cc2538 NIST curves
*
* NIST curves for various key sizes
* @{
*
* \file
* NIST curves for various key sizes
*/
#ifndef ECC_CURVE_H_
#define ECC_CURVE_H_
/*
* NIST P-256, X9.62 prime256v1
*/
ecc_curve_info_t nist_p_256;
/*
* NIST P-192, X9.62 prime192v1
*/
ecc_curve_info_t nist_p_192;
#endif /* CURVE_INFO_H_ */
/**
* @}
* @}
*/

559
cpu/cc2538/dev/ecc-driver.c Normal file
View file

@ -0,0 +1,559 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2014 Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-ecc
* @{
*
* \file
* Implementation of the cc2538 ECC driver
*/
#include "ecc-driver.h"
#include "reg.h"
#include "dev/nvic.h"
#define ASSERT(IF) if(!(IF)) { return PKA_STATUS_INVALID_PARAM; }
/*---------------------------------------------------------------------------*/
uint8_t
ecc_mul_start(uint32_t *scalar, ec_point_t *ec_point,
ecc_curve_info_t *curve, uint32_t *result_vector,
struct process *process)
{
uint8_t extraBuf;
uint32_t offset;
int i;
/* Check for the arguments. */
ASSERT(NULL != scalar);
ASSERT(NULL != ec_point);
ASSERT(NULL != ec_point->x);
ASSERT(NULL != ec_point->y);
ASSERT(NULL != curve);
ASSERT(curve->size <= PKA_MAX_CURVE_SIZE);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no PKA operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Calculate the extra buffer requirement. */
extraBuf = 2 + curve->size % 2;
/* Update the A ptr with the offset address of the PKA RAM location
* where the scalar will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the scalar in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *scalar++;
}
/* Determine the offset for the next data. */
offset += 4 * (i + (curve->size % 2));
/* Update the B ptr with the offset address of the PKA RAM location
* where the curve parameters will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Write curve parameter 'p' as 1st part of vector B immediately
* following vector A at PKA RAM */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->prime[i];
}
/* Determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Copy curve parameter 'a' in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->a[i];
}
/* Determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Copy curve parameter 'b' in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->b[i];
}
/* Determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Update the C ptr with the offset address of the PKA RAM location
* where the x, y will be stored. */
REG(PKA_CPTR) = offset >> 2;
/* Write elliptic curve point.x co-ordinate value. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point->x[i];
}
/* Determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Write elliptic curve point.y co-ordinate value. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point->y[i];
}
/* Determine the offset for the next data. */
offset += 4 * (i + extraBuf);
/* Update the result location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM. */
REG(PKA_DPTR) = offset >> 2;
/* Load length registers. */
REG(PKA_ALENGTH) = curve->size;
REG(PKA_BLENGTH) = curve->size;
/* set the PKA function to ECC-MULT and start the operation. */
REG(PKA_FUNCTION) = 0x0000D000;
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
ecc_mul_get_result(ec_point_t *ec_point,
uint32_t result_vector)
{
int i;
uint32_t addr;
uint32_t regMSWVal;
uint32_t len;
/* Check for the arguments. */
ASSERT(NULL != ec_point);
ASSERT(NULL != ec_point->x);
ASSERT(NULL != ec_point->y);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is completed. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
if(REG(PKA_SHIFT) == 0x00000000) {
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
addr = result_vector;
/* copy the x co-ordinate value of the result from vector D into
* the \e ec_point. */
for(i = 0; i < len; i++) {
ec_point->x[i] = REG(addr + 4 * i);
}
addr += 4 * (i + 2 + len % 2);
/* copy the y co-ordinate value of the result from vector D into
* the \e ec_point. */
for(i = 0; i < len; i++) {
ec_point->y[i] = REG(addr + 4 * i);
}
return PKA_STATUS_SUCCESS;
} else {
return PKA_STATUS_FAILURE;
}
}
/*---------------------------------------------------------------------------*/
uint8_t
ecc_mul_gen_pt_start(uint32_t *scalar, ecc_curve_info_t *curve,
uint32_t *result_vector, struct process *process)
{
uint8_t extraBuf;
uint32_t offset;
int i;
/* check for the arguments. */
ASSERT(NULL != scalar);
ASSERT(NULL != curve);
ASSERT(curve->size <= PKA_MAX_CURVE_SIZE);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Calculate the extra buffer requirement. */
extraBuf = 2 + curve->size % 2;
/* Update the A ptr with the offset address of the PKA RAM location
* where the scalar will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the scalar in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = *scalar++;
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + (curve->size % 2));
/* Update the B ptr with the offset address of the PKA RAM location
* where the curve parameters will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Write curve parameter 'p' as 1st part of vector B. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->prime[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Write curve parameter 'a' in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->a[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* write curve parameter 'b' in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->b[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Update the C ptr with the offset address of the PKA RAM location
* where the x, y will be stored. */
REG(PKA_CPTR) = offset >> 2;
/* Write x co-ordinate value of the Generator point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->x[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Write y co-ordinate value of the Generator point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->y[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Update the result location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM. */
REG(PKA_DPTR) = offset >> 2;
/* Load length registers. */
REG(PKA_ALENGTH) = curve->size;
REG(PKA_BLENGTH) = curve->size;
/* Set the PKA function to ECC-MULT and start the operation. */
REG(PKA_FUNCTION) = 0x0000D000;
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
ecc_mul_gen_pt_get_result(ec_point_t *ec_point,
uint32_t result_vector)
{
int i;
uint32_t regMSWVal;
uint32_t addr;
uint32_t len;
/* Check for the arguments. */
ASSERT(NULL != ec_point);
ASSERT(NULL != ec_point->x);
ASSERT(NULL != ec_point->y);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
/* Verify that the operation is completed. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
if(REG(PKA_SHIFT) == 0x00000000) {
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
addr = result_vector;
/* Copy the x co-ordinate value of the result from vector D into the
* EC point. */
for(i = 0; i < len; i++) {
ec_point->x[i] = REG(addr + 4 * i);
}
addr += 4 * (i + 2 + len % 2);
/* Copy the y co-ordinate value of the result from vector D into the
* EC point. */
for(i = 0; i < len; i++) {
ec_point->y[i] = REG(addr + 4 * i);
}
return PKA_STATUS_SUCCESS;
} else {
return PKA_STATUS_FAILURE;
}
}
/*---------------------------------------------------------------------------*/
uint8_t
ecc_add_start(ec_point_t *ec_point1, ec_point_t *ec_point2,
ecc_curve_info_t *curve, uint32_t *result_vector,
struct process *process)
{
uint8_t extraBuf;
uint32_t offset;
int i;
/* Check for the arguments. */
ASSERT(NULL != ec_point1);
ASSERT(NULL != ec_point1->x);
ASSERT(NULL != ec_point1->y);
ASSERT(NULL != ec_point2);
ASSERT(NULL != ec_point2->x);
ASSERT(NULL != ec_point2->y);
ASSERT(NULL != curve);
ASSERT(NULL != result_vector);
offset = 0;
/* Make sure no operation is in progress. */
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Calculate the extra buffer requirement. */
extraBuf = 2 + curve->size % 2;
/* Update the A ptr with the offset address of the PKA RAM location
* where the first ecPt will be stored. */
REG(PKA_APTR) = offset >> 2;
/* Load the x co-ordinate value of the first EC point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point1->x[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Load the y co-ordinate value of the first EC point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point1->y[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Update the B ptr with the offset address of the PKA RAM location
* where the curve parameters will be stored. */
REG(PKA_BPTR) = offset >> 2;
/* Write curve parameter 'p' as 1st part of vector B */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->prime[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Write curve parameter 'a'. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = (uint32_t)curve->a[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Update the C ptr with the offset address of the PKA RAM location
* where the ecPt2 will be stored. */
REG(PKA_CPTR) = offset >> 2;
/* Load the x co-ordinate value of the second EC point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point2->x[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Load the y co-ordinate value of the second EC point in PKA RAM. */
for(i = 0; i < curve->size; i++) {
REG(PKA_RAM_BASE + offset + 4 * i) = ec_point2->y[i];
}
/* Determine the offset in PKA RAM for the next data. */
offset += 4 * (i + extraBuf);
/* Copy the result vector location. */
*result_vector = PKA_RAM_BASE + offset;
/* Load D ptr with the result location in PKA RAM. */
REG(PKA_DPTR) = offset >> 2;
/* Load length registers. */
REG(PKA_BLENGTH) = curve->size;
/* Set the PKA Function to ECC-ADD and start the operation. */
REG(PKA_FUNCTION) = 0x0000B000;
/* Enable Interrupt */
if(process != NULL) {
pka_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_enable(NVIC_INT_PKA);
}
return PKA_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
ecc_add_get_result(ec_point_t *ec_point, uint32_t result_vector)
{
uint32_t regMSWVal;
uint32_t addr;
int i;
uint32_t len;
/* Check for the arguments. */
ASSERT(NULL != ec_point);
ASSERT(NULL != ec_point->x);
ASSERT(NULL != ec_point->y);
ASSERT(result_vector > PKA_RAM_BASE);
ASSERT(result_vector < (PKA_RAM_BASE + PKA_RAM_SIZE));
if((REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) != 0) {
return PKA_STATUS_OPERATION_INPRG;
}
/* Disable Interrupt */
nvic_interrupt_disable(NVIC_INT_PKA);
pka_register_process_notification(NULL);
if(REG(PKA_SHIFT) == 0x00000000) {
/* Get the MSW register value. */
regMSWVal = REG(PKA_MSW);
/* Check to make sure that the result vector is not all zeroes. */
if(regMSWVal & PKA_MSW_RESULT_IS_ZERO) {
return PKA_STATUS_RESULT_0;
}
/* Get the length of the result. */
len = ((regMSWVal & PKA_MSW_MSW_ADDRESS_M) + 1)
- ((result_vector - PKA_RAM_BASE) >> 2);
addr = result_vector;
/* Copy the x co-ordinate value of result from vector D into the
* the output EC Point. */
for(i = 0; i < len; i++) {
ec_point->x[i] = REG(addr + 4 * i);
}
addr += 4 * (i + 2 + len % 2);
/* Copy the y co-ordinate value of result from vector D into the
* the output EC Point. */
for(i = 0; i < len; i++) {
ec_point->y[i] = REG(addr + 4 * i);
}
return PKA_STATUS_SUCCESS;
} else {
return PKA_STATUS_FAILURE;
}
}
/** @} */

227
cpu/cc2538/dev/ecc-driver.h Normal file
View file

@ -0,0 +1,227 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2014 Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-pka
* @{
*
* \defgroup cc2538-ecc cc2538 ECC driver
*
* Driver for the cc2538 ECC mode of the PKC engine
* @{
*
* \file
* Header file for the cc2538 ECC driver
*/
#ifndef ECC_DRIVER_H_
#define ECC_DRIVER_H_
#include "contiki.h"
#include "pka.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \name ECC structures
* @{
*/
typedef struct {
const char *name; /**< Name of the curve. */
const uint8_t size; /**< Size of the curve in 32-bit word. */
const uint32_t *prime; /**< The prime that defines the field of the curve. */
const uint32_t *n; /**< Order of the curve. */
const uint32_t *a; /**< Co-efficient a of the equation. */
const uint32_t *b; /**< co-efficient b of the equation. */
const uint32_t *x; /**< x co-ordinate value of the generator point. */
const uint32_t *y; /**< y co-ordinate value of the generator point. */
} ecc_curve_info_t;
typedef struct {
uint32_t x[12]; /**< Pointer to value of the x co-ordinate. */
uint32_t y[12]; /**< Pointer to value of the y co-ordinate. */
} ec_point_t;
/** @} */
/*---------------------------------------------------------------------------*/
/** \name ECC functions
* \note Not all sequencer functions are implemented in this driver
* look at the CC2538 manual for a complete list.
* @{
*/
/** \brief Starts ECC Multiplication.
*
* \param scalar Pointer to the buffer containing the scalar
* value to be multiplied.
* \param ec_point Pointer to the structure containing the
* elliptic curve point to be multiplied. The point should be
* on the given curve.
* \param curve Pointer to the structure containing the curve
* info.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the Elliptical curve cryptography (ECC) point
* multiplication operation on the EC point and the scalar value.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t ecc_mul_start(uint32_t *scalar,
ec_point_t *ec_point,
ecc_curve_info_t *curve,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of ECC Multiplication
*
* \param ec_point Pointer to the structure where the resultant EC
* point will be stored. The callee is responsible to allocate the
* space for the ec point structure and the x and y co-ordinate as well.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKAECCMultiplyStart().
*
* This function gets the result of ecc point multiplication operation on the
* ec point and the scalar value, previously started using the function
* \sa PKAECCMultiplyStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
*/
uint8_t ecc_mul_get_result(ec_point_t *ec_point,
uint32_t result_vector);
/** \brief Starts the ECC Multiplication with Generator point.
*
* \param scalar Pointer to the buffer containing the
* scalar value.
* \param curve Pointer to the structure containing the curve
* info.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the ecc point multiplication operation of the
* scalar value with the well known generator point of the given curve.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t ecc_mul_gen_pt_start(uint32_t *scalar,
ecc_curve_info_t *curve,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of ECC Multiplication with Generator point.
*
* \param ec_point Pointer to the structure where the resultant EC
* point will be stored. The callee is responsible to allocate the
* space for the ec point structure and the x and y co-ordinate as well.
* \param result_vector Address of the result location which
* was provided by the start function \sa PKAECCMultGenPtStart().
*
* This function gets the result of ecc point multiplication operation on the
* scalar point and the known generator point on the curve, previously started
* using the function \sa PKAECCMultGenPtStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
*/
uint8_t ecc_mul_gen_pt_get_result(ec_point_t *ec_point,
uint32_t result_vector);
/** \brief Starts the ECC Addition.
*
* \param ec_point1 Pointer to the structure containing the first
* ecc point.
* \param ec_point2 Pointer to the structure containing the
* second ecc point.
* \param curve Pointer to the structure containing the curve
* info.
* \param result_vector Pointer to the result vector location
* which will be set by this function.
* \param process Process to be polled upon completion of the
* operation, or \c NULL
*
* This function starts the ecc point addition operation on the
* two given ec points and generates the resultant ecc point.
*
* \retval PKA_STATUS_SUCCESS if successful in starting the operation.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy doing
* some other operation.
*/
uint8_t ecc_add_start(ec_point_t *ec_point1, ec_point_t *ec_point2,
ecc_curve_info_t *curve,
uint32_t *result_vector,
struct process *process);
/** \brief Gets the result of the ECC Addition
*
* \param ptOutEcPt Pointer to the structure where the resultant
* point will be stored. The callee is responsible to allocate memory,
* for the ec point structure including the memory for x and y
* co-ordinate values.
* \param ui32ResultLoc Address of the result location which
* was provided by the function \sa PKAECCAddStart().
*
* This function gets the result of ecc point addition operation on the
* on the two given ec points, previously started using the function \sa
* PKAECCAddStart().
*
* \retval PKA_STATUS_SUCCESS if the operation is successful.
* \retval PKA_STATUS_OPERATION_INPRG if the PKA hw module is busy performing
* the operation.
* \retval PKA_STATUS_RESULT_0 if the result is all zeroes.
* \retval PKA_STATUS_FAILURE if the operation is not successful.
*/
uint8_t ecc_add_get_result(ec_point_t *ptOutEcPt, uint32_t ui32ResultLoc);
/** @} */
#endif /* ECC_DRIVER_H_ */
/**
* @}
* @}
*/

128
cpu/cc2538/dev/pka.c Normal file
View file

@ -0,0 +1,128 @@
/*
* Original file:
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2014 Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-pka
* @{
*
* \file
* Implementation of the cc2538 PKA engine driver
*/
#include "contiki.h"
#include "sys/energest.h"
#include "dev/pka.h"
#include "dev/sys-ctrl.h"
#include "dev/nvic.h"
#include "lpm.h"
#include "reg.h"
#include <stdbool.h>
#include <stdint.h>
static volatile struct process *notification_process = NULL;
/*---------------------------------------------------------------------------*/
/** \brief The PKA engine ISR
*
* This is the interrupt service routine for the PKA engine.
*
* This ISR is called at worst from PM0, so lpm_exit() does not need
* to be called.
*/
void
pka_isr(void)
{
ENERGEST_ON(ENERGEST_TYPE_IRQ);
nvic_interrupt_unpend(NVIC_INT_PKA);
nvic_interrupt_disable(NVIC_INT_PKA);
if(notification_process != NULL) {
process_poll((struct process *)notification_process);
notification_process = NULL;
}
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
/*---------------------------------------------------------------------------*/
static bool
permit_pm1(void)
{
return (REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) == 0;
}
/*---------------------------------------------------------------------------*/
void
pka_init(void)
{
volatile int i;
lpm_register_peripheral(permit_pm1);
pka_enable();
/* Reset the PKA engine */
REG(SYS_CTRL_SRSEC) |= SYS_CTRL_SRSEC_PKA;
for(i = 0; i < 16; i++) {
REG(SYS_CTRL_SRSEC) &= ~SYS_CTRL_SRSEC_PKA;
}
}
/*---------------------------------------------------------------------------*/
void
pka_enable(void)
{
/* Enable the clock for the PKA engine */
REG(SYS_CTRL_RCGCSEC) |= SYS_CTRL_RCGCSEC_PKA;
REG(SYS_CTRL_SCGCSEC) |= SYS_CTRL_SCGCSEC_PKA;
REG(SYS_CTRL_DCGCSEC) |= SYS_CTRL_DCGCSEC_PKA;
}
/*---------------------------------------------------------------------------*/
void
pka_disable(void)
{
/* Gate the clock for the PKA engine */
REG(SYS_CTRL_RCGCSEC) &= ~SYS_CTRL_RCGCSEC_PKA;
REG(SYS_CTRL_SCGCSEC) &= ~SYS_CTRL_SCGCSEC_PKA;
REG(SYS_CTRL_DCGCSEC) &= ~SYS_CTRL_DCGCSEC_PKA;
}
/*---------------------------------------------------------------------------*/
uint8_t
pka_check_status(void)
{
return (REG(PKA_FUNCTION) & PKA_FUNCTION_RUN) == 0;
}
void
pka_register_process_notification(struct process *p)
{
notification_process = p;
}
/** @} */

871
cpu/cc2538/dev/pka.h Normal file
View file

@ -0,0 +1,871 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2014 Andreas Dröscher <contiki@anticat.ch>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538
* @{
*
* \defgroup cc2538-pka cc2538 PKA engine
*
* Driver for the cc2538 PKA engine
* @{
*
* \file
* Header file for the cc2538 PKA engine driver
*/
#ifndef PKA_H_
#define PKA_H_
#include "contiki.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \name PKA memory
* @{
*/
#define PKA_RAM_BASE 0x44006000 /**< PKA Memory Address */
#define PKA_RAM_SIZE 0x800 /**< PKA Memory Size */
#define PKA_MAX_CURVE_SIZE 12 /**< Define for the maximum curve
size supported by the PKA module
in 32 bit word. */
#define PKA_MAX_LEN 12 /**< Define for the maximum length of
the big number supported by the
PKA module in 32 bit word. */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA register offsets
* @{
*/
#define PKA_APTR 0x44004000 /**< PKA vector A address During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_BPTR 0x44004004 /**< PKA vector B address During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_CPTR 0x44004008 /**< PKA vector C address During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_DPTR 0x4400400C /**< PKA vector D address During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_ALENGTH 0x44004010 /**< PKA vector A length During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_BLENGTH 0x44004014 /**< PKA vector B length During
execution of basic PKCP
operations, this register is
double buffered and can be
written with a new value for the
next operation; when not
written, the value remains
intact. During the execution of
sequencer-controlled complex
operations, this register may
not be written and its value is
undefined at the conclusion of
the operation. The driver
software cannot rely on the
written value to remain intact. */
#define PKA_SHIFT 0x44004018 /**< PKA bit shift value For basic
PKCP operations, modifying the
contents of this register is
made impossible while the
operation is being performed.
For the ExpMod-variable and
ExpMod-CRT operations, this
register is used to indicate the
number of odd powers to use
(directly as a value in the
range 1-16). For the ModInv and
ECC operations, this register is
used to hold a completion code. */
#define PKA_FUNCTION 0x4400401C /**< PKA function This register
contains the control bits to
start basic PKCP as well as
complex sequencer operations.
The run bit can be used to poll
for the completion of the
operation. Modifying bits [11:0]
is made impossible during the
execution of a basic PKCP
operation. During the execution
of sequencer-controlled complex
operations, this register is
modified; the run and stall
result bits are set to zero at
the conclusion, but other bits
are undefined. Attention:
Continuously reading this
register to poll the run bit is
not allowed when executing
complex sequencer operations
(the sequencer cannot access the
PKCP when this is done). Leave
at least one sysclk cycle
between poll operations. */
#define PKA_COMPARE 0x44004020 /**< PKA compare result This
register provides the result of
a basic PKCP compare operation.
It is updated when the run bit
in the PKA_FUNCTION register is
reset at the end of that
operation. Status after a
complex sequencer operation is
unknown */
#define PKA_MSW 0x44004024 /**< PKA most-significant-word of
result vector This register
indicates the (word) address in
the PKA RAM where the most
significant nonzero 32-bit word
of the result is stored. Should
be ignored for modulo
operations. For basic PKCP
operations, this register is
updated when the run bit in the
PKA_FUNCTION register is reset
at the end of the operation. For
the complex-sequencer controlled
operations, updating of the
final value matching the actual
result is done near the end of
the operation; note that the
result is only meaningful if no
errors were detected and that
for ECC operations, the PKA_MSW
register will provide
information for the x-coordinate
of the result point only. */
#define PKA_DIVMSW 0x44004028 /**< PKA most-significant-word of
divide remainder This register
indicates the (32-bit word)
address in the PKA RAM where the
most significant nonzero 32-bit
word of the remainder result for
the basic divide and modulo
operations is stored. Bits [4:0]
are loaded with the bit number
of the most-significant nonzero
bit in the most-significant
nonzero word when MS one control
bit is set. For divide, modulo,
and MS one reporting, this
register is updated when the RUN
bit in the PKA_FUNCTION register
is reset at the end of the
operation. For the complex
sequencer controlled operations,
updating of bits [4:0] of this
register with the
most-significant bit location of
the actual result is done near
the end of the operation. The
result is meaningful only if no
errors were detected and that
for ECC operations; the
PKA_DIVMSW register provides
information for the x-coordinate
of the result point only. */
#define PKA_SEQ_CTRL 0x440040C8 /**< PKA sequencer control and
status register The sequencer is
interfaced with the outside
world through a single control
and status register. With the
exception of bit [31], the
actual use of bits in the
separate sub-fields of this
register is determined by the
sequencer firmware. This
register need only be accessed
when the sequencer program is
stored in RAM. The reset value
of the RESTE bit depends upon
the option chosen for sequencer
program storage. */
#define PKA_OPTIONS 0x440040F4 /**< PKA hardware options register
This register provides the host
with a means to determine the
hardware configuration
implemented in this PKA engine,
focused on options that have an
effect on software interacting
with the module. Note: (32 x
(1st LNME nr. of PEs + 1st LNME
FIFO RAM depth - 10)) equals the
maximum modulus vector length
(in bits) that can be handled by
the modular exponentiation and
ECC operations executed on a PKA
engine that includes an LNME. */
#define PKA_SW_REV 0x440040F8 /**< PKA firmware revision and
capabilities register This
register allows the host access
to the internal firmware
revision number of the PKA
Engine for software driver
matching and diagnostic
purposes. This register also
contains a field that encodes
the capabilities of the embedded
firmware. The PKA_SW_REV
register is written by the
firmware within a few clock
cycles after starting up that
firmware. The hardware reset
value is zero, indicating that
the information has not been
written yet. */
#define PKA_REVISION 0x440040FC /**< PKA hardware revision register
This register allows the host
access to the hardware revision
number of the PKA engine for
software driver matching and
diagnostic purposes. It is
always located at the highest
address in the access space of
the module and contains an
encoding of the EIP number (with
its complement as signature) for
recognition of the hardware
module. */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_APTR register registers bit fields
* @{
*/
#define PKA_APTR_APTR_M 0x000007FF /**< This register specifies the
location of vector A within the
PKA RAM. Vectors are identified
through the location of their
least-significant 32-bit word.
Note that bit [0] must be zero
to ensure that the vector starts
at an 8-byte boundary. */
#define PKA_APTR_APTR_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_BPTR register registers bit fields
* @{
*/
#define PKA_BPTR_BPTR_M 0x000007FF /**< This register specifies the
location of vector B within the
PKA RAM. Vectors are identified
through the location of their
least-significant 32-bit word.
Note that bit [0] must be zero
to ensure that the vector starts
at an 8-byte boundary. */
#define PKA_BPTR_BPTR_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_CPTR register registers bit fields
* @{
*/
#define PKA_CPTR_CPTR_M 0x000007FF /**< This register specifies the
location of vector C within the
PKA RAM. Vectors are identified
through the location of their
least-significant 32-bit word.
Note that bit [0] must be zero
to ensure that the vector starts
at an 8-byte boundary. */
#define PKA_CPTR_CPTR_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_DPTR register registers bit fields
* @{
*/
#define PKA_DPTR_DPTR_M 0x000007FF /**< This register specifies the
location of vector D within the
PKA RAM. Vectors are identified
through the location of their
least-significant 32-bit word.
Note that bit [0] must be zero
to ensure that the vector starts
at an 8-byte boundary. */
#define PKA_DPTR_DPTR_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_ALENGTH register registers bit fields
* @{
*/
#define PKA_ALENGTH_ALENGTH_M 0x000001FF /**< This register specifies the
length (in 32-bit words) of
Vector A. */
#define PKA_ALENGTH_ALENGTH_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_BLENGTH register registers bit fields
* @{
*/
#define PKA_BLENGTH_BLENGTH_M 0x000001FF /**< This register specifies the
length (in 32-bit words) of
Vector B. */
#define PKA_BLENGTH_BLENGTH_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_SHIFT register registers bit fields
* @{
*/
#define PKA_SHIFT_NUM_BITS_TO_SHIFT_M \
0x0000001F /**< This register specifies the
number of bits to shift the
input vector (in the range 0-31)
during a Rshift or Lshift
operation. */
#define PKA_SHIFT_NUM_BITS_TO_SHIFT_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_FUNCTION register registers bit fields
* @{
*/
#define PKA_FUNCTION_STALL_RESULT \
0x01000000 /**< When written with a 1b,
updating of the PKA_COMPARE,
PKA_MSW and PKA_DIVMSW
registers, as well as resetting
the run bit is stalled beyond
the point that a running
operation is actually finished.
Use this to allow software
enough time to read results from
a previous operation when the
newly started operation is known
to take only a short amount of
time. If a result is waiting,
the result registers is updated
and the run bit is reset in the
clock cycle following writing
the stall result bit back to 0b.
The Stall result function may
only be used for basic PKCP
operations. */
#define PKA_FUNCTION_STALL_RESULT_M \
0x01000000
#define PKA_FUNCTION_STALL_RESULT_S 24
#define PKA_FUNCTION_RUN 0x00008000 /**< The host sets this bit to
instruct the PKA module to begin
processing the basic PKCP or
complex sequencer operation.
This bit is reset low
automatically when the operation
is complete. The complement of
this bit is output as
interrupts[1]. After a reset,
the run bit is always set to 1b.
Depending on the option, program
ROM or program RAM, the
following applies: Program ROM -
The first sequencer instruction
sets the bit to 0b. This is done
immediately after the hardware
reset is released. Program RAM -
The sequencer must set the bit
to 0b. As a valid firmware may
not have been loaded, the
sequencer is held in software
reset after the hardware reset
is released (the reset bit in
PKA_SEQ_CRTL is set to 1b).
After the FW image is loaded and
the Reset bit is cleared, the
sequencer starts to execute the
FW. The first instruction clears
the run bit. In both cases a few
clock cycles are needed before
the first instruction is
executed and the run bit state
has been propagated. */
#define PKA_FUNCTION_RUN_M 0x00008000
#define PKA_FUNCTION_RUN_S 15
#define PKA_FUNCTION_SEQUENCER_OPERATIONS_M \
0x00007000 /**< These bits select the complex
sequencer operation to perform:
000b: None 001b: ExpMod-CRT
010b: ExpMod-ACT4 (compatible
with EIP2315) 011b: ECC-ADD (if
available in firmware, otherwise
reserved) 100b: ExpMod-ACT2
(compatible with EIP2316) 101b:
ECC-MUL (if available in
firmware, otherwise reserved)
110b: ExpMod-variable 111b:
ModInv (if available in
firmware, otherwise reserved)
The encoding of these operations
is determined by sequencer
firmware. */
#define PKA_FUNCTION_SEQUENCER_OPERATIONS_S 12
#define PKA_FUNCTION_COPY 0x00000800 /**< Perform copy operation */
#define PKA_FUNCTION_COPY_M 0x00000800
#define PKA_FUNCTION_COPY_S 11
#define PKA_FUNCTION_COMPARE 0x00000400 /**< Perform compare operation */
#define PKA_FUNCTION_COMPARE_M 0x00000400
#define PKA_FUNCTION_COMPARE_S 10
#define PKA_FUNCTION_MODULO 0x00000200 /**< Perform modulo operation */
#define PKA_FUNCTION_MODULO_M 0x00000200
#define PKA_FUNCTION_MODULO_S 9
#define PKA_FUNCTION_DIVIDE 0x00000100 /**< Perform divide operation */
#define PKA_FUNCTION_DIVIDE_M 0x00000100
#define PKA_FUNCTION_DIVIDE_S 8
#define PKA_FUNCTION_LSHIFT 0x00000080 /**< Perform left shift operation */
#define PKA_FUNCTION_LSHIFT_M 0x00000080
#define PKA_FUNCTION_LSHIFT_S 7
#define PKA_FUNCTION_RSHIFT 0x00000040 /**< Perform right shift operation */
#define PKA_FUNCTION_RSHIFT_M 0x00000040
#define PKA_FUNCTION_RSHIFT_S 6
#define PKA_FUNCTION_SUBTRACT 0x00000020 /**< Perform subtract operation */
#define PKA_FUNCTION_SUBTRACT_M 0x00000020
#define PKA_FUNCTION_SUBTRACT_S 5
#define PKA_FUNCTION_ADD 0x00000010 /**< Perform add operation */
#define PKA_FUNCTION_ADD_M 0x00000010
#define PKA_FUNCTION_ADD_S 4
#define PKA_FUNCTION_MS_ONE 0x00000008 /**< Loads the location of the Most
Significant one bit within the
result word indicated in the
PKA_MSW register into bits [4:0]
of the PKA_DIVMSW register - can
only be used with basic PKCP
operations, except for Divide,
Modulo and Compare. */
#define PKA_FUNCTION_MS_ONE_M 0x00000008
#define PKA_FUNCTION_MS_ONE_S 3
#define PKA_FUNCTION_ADDSUB 0x00000002 /**< Perform combined add/subtract
operation */
#define PKA_FUNCTION_ADDSUB_M 0x00000002
#define PKA_FUNCTION_ADDSUB_S 1
#define PKA_FUNCTION_MULTIPLY 0x00000001 /**< Perform multiply operation */
#define PKA_FUNCTION_MULTIPLY_M 0x00000001
#define PKA_FUNCTION_MULTIPLY_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_COMPARE register registers bit fields
* @{
*/
#define PKA_COMPARE_A_GREATER_THAN_B \
0x00000004 /**< Vector_A is greater than
Vector_B */
#define PKA_COMPARE_A_GREATER_THAN_B_M \
0x00000004
#define PKA_COMPARE_A_GREATER_THAN_B_S 2
#define PKA_COMPARE_A_LESS_THAN_B \
0x00000002 /**< Vector_A is less than Vector_B */
#define PKA_COMPARE_A_LESS_THAN_B_M \
0x00000002
#define PKA_COMPARE_A_LESS_THAN_B_S 1
#define PKA_COMPARE_A_EQUALS_B 0x00000001 /**< Vector_A is equal to Vector_B */
#define PKA_COMPARE_A_EQUALS_B_M \
0x00000001
#define PKA_COMPARE_A_EQUALS_B_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_MSW register registers bit fields
* @{
*/
#define PKA_MSW_RESULT_IS_ZERO 0x00008000 /**< The result vector is all
zeroes, ignore the address
returned in bits [10:0] */
#define PKA_MSW_RESULT_IS_ZERO_M \
0x00008000
#define PKA_MSW_RESULT_IS_ZERO_S 15
#define PKA_MSW_MSW_ADDRESS_M 0x000007FF /**< Address of the most-significant
nonzero 32-bit word of the
result vector in PKA RAM */
#define PKA_MSW_MSW_ADDRESS_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_DIVMSW register registers bit fields
* @{
*/
#define PKA_DIVMSW_RESULT_IS_ZERO \
0x00008000 /**< The result vector is all
zeroes, ignore the address
returned in bits [10:0] */
#define PKA_DIVMSW_RESULT_IS_ZERO_M \
0x00008000
#define PKA_DIVMSW_RESULT_IS_ZERO_S 15
#define PKA_DIVMSW_MSW_ADDRESS_M \
0x000007FF /**< Address of the most significant
nonzero 32-bit word of the
remainder result vector in PKA
RAM */
#define PKA_DIVMSW_MSW_ADDRESS_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_SEQ_CTRL register registers bit fields
* @{
*/
#define PKA_SEQ_CTRL_RESET 0x80000000 /**< Option program ROM: Reset value
= 0. Read/Write, reset value 0b
(ZERO). Writing 1b resets the
sequencer, write to 0b to
restart operations again. As the
reset value is 0b, the sequencer
will automatically start
operations executing from
program ROM. This bit should
always be written with zero and
ignored when reading this
register. Option Program RAM:
Reset value =1. Read/Write,
reset value 1b (ONE). When 1b,
the sequencer is held in a reset
state and the PKA_PROGRAM area
is accessible for loading the
sequencer program (while the
PKA_DATA_RAM is inaccessible),
write to 0b to (re)start
sequencer operations and disable
PKA_PROGRAM area accessibility
(also enables the PKA_DATA_RAM
accesses). Resetting the
sequencer (in order to load
other firmware) should only be
done when the PKA Engine is not
performing any operations (i.e.
the run bit in the PKA_FUNCTION
register should be zero). */
#define PKA_SEQ_CTRL_RESET_M 0x80000000
#define PKA_SEQ_CTRL_RESET_S 31
#define PKA_SEQ_CTRL_SEQUENCER_STATUS_M \
0x0000FF00 /**< These read-only bits can be
used by the sequencer to
communicate status to the
outside world. Bit [8] is also
used as sequencer interrupt,
with the complement of this bit
ORed into the run bit in
PKA_FUNCTION. This field should
always be written with zeroes
and ignored when reading this
register. */
#define PKA_SEQ_CTRL_SEQUENCER_STATUS_S 8
#define PKA_SEQ_CTRL_SW_CONTROL_STATUS_M \
0x000000FF /**< These bits can be used by
software to trigger sequencer
operations. External logic can
set these bits by writing 1b,
cannot reset them by writing 0b.
The sequencer can reset these
bits by writing 0b, cannot set
them by writing 1b. Setting the
run bit in PKA_FUNCTION together
with a nonzero sequencer
operations field automatically
sets bit [0] here. This field
should always be written with
zeroes and ignored when reading
this register. */
#define PKA_SEQ_CTRL_SW_CONTROL_STATUS_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_OPTIONS register registers bit fields
* @{
*/
#define PKA_OPTIONS_FIRST_LNME_FIFO_DEPTH_M \
0xFF000000 /**< Number of words in the first
LNME's FIFO RAM Should be
ignored if LNME configuration is
0. The contents of this field
indicate the actual depth as
selected by the LNME FIFO RAM
size strap input, fifo_size_sel.
Note: Reset value is undefined */
#define PKA_OPTIONS_FIRST_LNME_FIFO_DEPTH_S 24
#define PKA_OPTIONS_FIRST_LNME_NR_OF_PES_M \
0x003F0000 /**< Number of processing elements
in the pipeline of the first
LNME Should be ignored if LNME
configuration is 0. Note: Reset
value is undefined. */
#define PKA_OPTIONS_FIRST_LNME_NR_OF_PES_S 16
#define PKA_OPTIONS_MMM3A 0x00001000 /**< Reserved for a future
functional extension to the LNME
Always 0b */
#define PKA_OPTIONS_MMM3A_M 0x00001000
#define PKA_OPTIONS_MMM3A_S 12
#define PKA_OPTIONS_INT_MASKING 0x00000800 /**< Value 0b indicates that the
main interrupt output (bit [1]
of the interrupts output bus) is
the direct complement of the run
bit in the PKA_CONTROL register,
value 1b indicates that
interrupt masking logic is
present for this output. Note:
Reset value is undefined */
#define PKA_OPTIONS_INT_MASKING_M \
0x00000800
#define PKA_OPTIONS_INT_MASKING_S 11
#define PKA_OPTIONS_PROTECTION_OPTION_M \
0x00000700 /**< Value 0 indicates no additional
protection against side channel
attacks, value 1 indicates the
SCAP option, value 3 indicates
the PROT option; other values
are reserved. Note: Reset value
is undefined */
#define PKA_OPTIONS_PROTECTION_OPTION_S 8
#define PKA_OPTIONS_PROGRAM_RAM 0x00000080 /**< Value 1b indicates sequencer
program storage in RAM, value 0b
in ROM. Note: Reset value is
undefined */
#define PKA_OPTIONS_PROGRAM_RAM_M \
0x00000080
#define PKA_OPTIONS_PROGRAM_RAM_S 7
#define PKA_OPTIONS_SEQUENCER_CONFIGURATION_M \
0x00000060 /**< Value 1 indicates a standard
sequencer; other values are
reserved. */
#define PKA_OPTIONS_SEQUENCER_CONFIGURATION_S 5
#define PKA_OPTIONS_LNME_CONFIGURATION_M \
0x0000001C /**< Value 0 indicates NO LNME,
value 1 indicates one standard
LNME (with alpha = 32, beta =
8); other values reserved. Note:
Reset value is undefined */
#define PKA_OPTIONS_LNME_CONFIGURATION_S 2
#define PKA_OPTIONS_PKCP_CONFIGURATION_M \
0x00000003 /**< Value 1 indicates a PKCP with a
16x16 multiplier, value 2
indicates a PKCP with a 32x32
multiplier, other values
reserved. Note: Reset value is
undefined. */
#define PKA_OPTIONS_PKCP_CONFIGURATION_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_SW_REV register registers bit fields
* @{
*/
#define PKA_SW_REV_FW_CAPABILITIES_M \
0xF0000000 /**< 4-bit binary encoding for the
functionality implemented in the
firmware. Value 0 indicates
basic ModExp with/without CRT.
Value 1 adds Modular Inversion,
value 2 adds Modular Inversion
and ECC operations. Values 3-15
are reserved. */
#define PKA_SW_REV_FW_CAPABILITIES_S 28
#define PKA_SW_REV_MAJOR_FW_REVISION_M \
0x0F000000 /**< 4-bit binary encoding of the
major firmware revision number */
#define PKA_SW_REV_MAJOR_FW_REVISION_S 24
#define PKA_SW_REV_MINOR_FW_REVISION_M \
0x00F00000 /**< 4-bit binary encoding of the
minor firmware revision number */
#define PKA_SW_REV_MINOR_FW_REVISION_S 20
#define PKA_SW_REV_FW_PATCH_LEVEL_M \
0x000F0000 /**< 4-bit binary encoding of the
firmware patch level, initial
release will carry value zero
Patches are used to remove bugs
without changing the
functionality or interface of a
module. */
#define PKA_SW_REV_FW_PATCH_LEVEL_S 16
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA_REVISION register registers bit fields
* @{
*/
#define PKA_REVISION_MAJOR_HW_REVISION_M \
0x0F000000 /**< 4-bit binary encoding of the
major hardware revision number */
#define PKA_REVISION_MAJOR_HW_REVISION_S 24
#define PKA_REVISION_MINOR_HW_REVISION_M \
0x00F00000 /**< 4-bit binary encoding of the
minor hardware revision number */
#define PKA_REVISION_MINOR_HW_REVISION_S 20
#define PKA_REVISION_HW_PATCH_LEVEL_M \
0x000F0000 /**< 4-bit binary encoding of the
hardware patch level, initial
release will carry value zero
Patches are used to remove bugs
without changing the
functionality or interface of a
module. */
#define PKA_REVISION_HW_PATCH_LEVEL_S 16
#define PKA_REVISION_COMPLEMENT_OF_BASIC_EIP_NUMBER_M \
0x0000FF00 /**< Bit-by-bit logic complement of
bits [7:0], EIP-28 gives 0xE3 */
#define PKA_REVISION_COMPLEMENT_OF_BASIC_EIP_NUMBER_S 8
#define PKA_REVISION_BASIC_EIP_NUMBER_M \
0x000000FF /**< 8-bit binary encoding of the
EIP number, EIP-28 gives 0x1C */
#define PKA_REVISION_BASIC_EIP_NUMBER_S 0
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA driver return codes
* @{
*/
#define PKA_STATUS_SUCCESS 0 /**< Success */
#define PKA_STATUS_FAILURE 1 /**< Failure */
#define PKA_STATUS_INVALID_PARAM 2 /**< Invalid parameter */
#define PKA_STATUS_BUF_UNDERFLOW 3 /**< Buffer underflow */
#define PKA_STATUS_RESULT_0 4 /**< Result is all zeros */
#define PKA_STATUS_A_GR_B 5 /**< Big number compare return status if
the first big num is greater than
the second. */
#define PKA_STATUS_A_LT_B 6 /**< Big number compare return status if
the first big num is less than the
second. */
#define PKA_STATUS_OPERATION_INPRG 7 /**< PKA operation is in progress. */
#define PKA_STATUS_OPERATION_NOT_INPRG 8 /**< No PKA operation is in progress. */
#define PKA_STATUS_SIGNATURE_INVALID 9 /**< Signature is invalid. */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name PKA functions
* @{
*/
/** \brief Enables and resets the PKA engine
*/
void pka_init(void);
/** \brief Enables the PKA engine
*/
void pka_enable(void);
/** \brief Disables the PKA engine
* \note Call this function to save power when the engine is unused.
*/
void pka_disable(void);
/** \brief Checks the status of the PKA engine operation
* \retval false Result not yet available, and no error occurred
* \retval true Result available, or error occurred
*/
uint8_t pka_check_status(void);
/** \brief Registers a process to be notified of the completion of a PKA
* operation
* \param p Process to be polled upon IRQ
* \note This function is only supposed to be called by the PKA drivers.
*/
void pka_register_process_notification(struct process *p);
/** @} */
#endif /* PKA_H_ */
/**
* @}
* @}
*/

View file

@ -101,7 +101,7 @@ static uint8_t max_pm;
#ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX
#else
#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 3
#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 4
#endif
static lpm_periph_permit_pm1_func_t
@ -128,8 +128,7 @@ periph_permit_pm1(void)
static void
enter_pm0(void)
{
ENERGEST_OFF(ENERGEST_TYPE_CPU);
ENERGEST_ON(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
/* We are only interested in IRQ energest while idle or in LPM */
ENERGEST_IRQ_RESTORE(irq_energest);
@ -147,8 +146,7 @@ enter_pm0(void)
/* Remember IRQ energest for next pass */
ENERGEST_IRQ_SAVE(irq_energest);
ENERGEST_ON(ENERGEST_TYPE_CPU);
ENERGEST_OFF(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
}
/*---------------------------------------------------------------------------*/
static void
@ -238,8 +236,7 @@ lpm_exit()
/* Remember IRQ energest for next pass */
ENERGEST_IRQ_SAVE(irq_energest);
ENERGEST_ON(ENERGEST_TYPE_CPU);
ENERGEST_OFF(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
}
/*---------------------------------------------------------------------------*/
void
@ -312,8 +309,7 @@ lpm_enter()
/* We are only interested in IRQ energest while idle or in LPM */
ENERGEST_IRQ_RESTORE(irq_energest);
ENERGEST_OFF(ENERGEST_TYPE_CPU);
ENERGEST_ON(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
/* Remember the current time so we can keep stats when we wake up */
if(LPM_CONF_STATS) {
@ -339,8 +335,7 @@ lpm_enter()
/* Remember IRQ energest for next pass */
ENERGEST_IRQ_SAVE(irq_energest);
ENERGEST_ON(ENERGEST_TYPE_CPU);
ENERGEST_OFF(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
} else {
/* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */
assert_wfi();

View file

@ -68,6 +68,7 @@ void usb_isr(void) WEAK_ALIAS(default_handler);
void uart0_isr(void) WEAK_ALIAS(default_handler);
void uart1_isr(void) WEAK_ALIAS(default_handler);
void crypto_isr(void);
void pka_isr(void);
/* Boot Loader Backdoor selection */
#if FLASH_CCA_CONF_BOOTLDR_BACKDOOR
@ -271,7 +272,7 @@ void(*const vectors[])(void) =
cc2538_rf_rx_tx_isr, /* 157 RFCORE RX/TX */
cc2538_rf_err_isr, /* 158 RFCORE Error */
crypto_isr, /* 159 AES */
default_handler, /* 160 PKA */
pka_isr, /* 160 PKA */
rtimer_isr, /* 161 SM Timer */
default_handler, /* 162 MACTimer */
};

View file

@ -38,7 +38,6 @@
#endif
#define CC_CONF_FUNCTION_POINTER_ARGS 1
#define CC_CONF_FASTCALL
#define CC_CONF_VA_ARGS 1
#define CC_CONF_UNSIGNED_CHAR_BUGS 0
#define CC_CONF_REGISTER_ARGS 0

View file

@ -41,6 +41,10 @@ LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch
OBJCOPY_FLAGS += -O binary --gap-fill 0xff
OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb
ifdef WERROR
CFLAGS += -Werror
endif
### Are we building with code size optimisations?
ifeq ($(SMALL),1)
CFLAGS += -Os

View file

@ -120,31 +120,35 @@ clock_init(void)
((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE;
}
/*---------------------------------------------------------------------------*/
static void
update_clock_variable(void)
{
uint32_t aon_rtc_secs_now;
uint32_t aon_rtc_secs_now2;
uint16_t aon_rtc_ticks_now;
do {
aon_rtc_secs_now = HWREG(AON_RTC_BASE + AON_RTC_O_SEC);
aon_rtc_ticks_now = HWREG(AON_RTC_BASE + AON_RTC_O_SUBSEC) >> 16;
aon_rtc_secs_now2 = HWREG(AON_RTC_BASE + AON_RTC_O_SEC);
} while(aon_rtc_secs_now != aon_rtc_secs_now2);
/* Convert AON RTC ticks to clock tick counter */
count = (aon_rtc_secs_now * CLOCK_SECOND) + (aon_rtc_ticks_now >> 9);
}
/*---------------------------------------------------------------------------*/
CCIF clock_time_t
clock_time(void)
{
update_clock_variable();
return (clock_time_t)(count & 0xFFFFFFFF);
}
/*---------------------------------------------------------------------------*/
void
clock_update(void)
{
bool interrupts_disabled;
uint32_t aon_rtc_secs_now;
uint16_t aon_rtc_ticks_now;
interrupts_disabled = ti_lib_int_master_disable();
aon_rtc_secs_now = HWREG(AON_RTC_BASE + AON_RTC_O_SEC);
aon_rtc_ticks_now = HWREG(AON_RTC_BASE + AON_RTC_O_SUBSEC) >> 16;
/* Convert AON RTC ticks to clock tick counter */
count = (aon_rtc_secs_now * CLOCK_SECOND) + (aon_rtc_ticks_now >> 9);
/* Re-enable interrupts */
if(!interrupts_disabled) {
ti_lib_int_master_enable();
}
update_clock_variable();
if(etimer_pending()) {
etimer_request_poll();

View file

@ -42,8 +42,61 @@
* \file
* Implementation of the CC13xx/CC26xx watchdog driver.
*/
#include "watchdog.h"
#include "contiki.h"
#include "dev/watchdog.h"
#include "ti-lib.h"
#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#ifdef CONTIKI_WATCHDOG_CONF_TIMER_TOP
#define CONTIKI_WATCHDOG_TIMER_TOP CONTIKI_WATCHDOG_CONF_TIMER_TOP
#else
#define CONTIKI_WATCHDOG_TIMER_TOP 0xFFFFF
#endif
#ifdef CONTIKI_WATCHDOG_CONF_LOCK_CONFIG
#define CONTIKI_WATCHDOG_LOCK_CONFIG CONTIKI_WATCHDOG_CONF_LOCK_CONFIG
#else
#define CONTIKI_WATCHDOG_LOCK_CONFIG 1
#endif
#define LOCK_INTERRUPTS_DISABLED 0x01
#define LOCK_REGISTERS_UNLOCKED 0x02
/*---------------------------------------------------------------------------*/
static uint32_t
unlock_config(void)
{
uint32_t ret = 0;
bool int_status;
if(CONTIKI_WATCHDOG_LOCK_CONFIG) {
int_status = ti_lib_int_master_disable();
if(ti_lib_watchdog_lock_state()) {
ret |= LOCK_REGISTERS_UNLOCKED;
ti_lib_watchdog_unlock();
}
ret |= (int_status) ? (0) : (LOCK_INTERRUPTS_DISABLED);
}
return ret;
}
/*---------------------------------------------------------------------------*/
static void
lock_config(uint32_t status)
{
if(CONTIKI_WATCHDOG_LOCK_CONFIG) {
if(status & LOCK_REGISTERS_UNLOCKED) {
ti_lib_watchdog_lock();
}
if(status & LOCK_INTERRUPTS_DISABLED) {
ti_lib_int_master_enable();
}
}
}
/*---------------------------------------------------------------------------*/
/**
* \brief Initialises the CC26xx WDT
@ -54,7 +107,8 @@
void
watchdog_init(void)
{
ti_lib_watchdog_reload_set(0xFFFFF);
ti_lib_watchdog_reload_set(CONTIKI_WATCHDOG_TIMER_TOP);
lock_config(LOCK_REGISTERS_UNLOCKED);
}
/*---------------------------------------------------------------------------*/
/**
@ -63,7 +117,12 @@ watchdog_init(void)
void
watchdog_start(void)
{
uint32_t lock_status = unlock_config();
watchdog_periodic();
ti_lib_watchdog_reset_enable();
lock_config(lock_status);
}
/*---------------------------------------------------------------------------*/
/**
@ -72,9 +131,23 @@ watchdog_start(void)
void
watchdog_periodic(void)
{
ti_lib_watchdog_reload_set(CONTIKI_WATCHDOG_TIMER_TOP);
ti_lib_watchdog_int_clear();
}
/*---------------------------------------------------------------------------*/
/**
* \brief Stops the WDT such that it won't timeout and cause MCU reset
*/
void
watchdog_stop(void)
{
uint32_t lock_status = unlock_config();
ti_lib_watchdog_reset_disable();
lock_config(lock_status);
}
/*---------------------------------------------------------------------------*/
/**
* \brief Manually trigger a WDT reboot
*/

View file

@ -50,6 +50,8 @@
/*---------------------------------------------------------------------------*/
/* Prototype of a function in clock.c. Called every time the handler fires */
void clock_update(void);
static rtimer_clock_t last_isr_time;
/*---------------------------------------------------------------------------*/
#define COMPARE_INCREMENT (RTIMER_SECOND / CLOCK_SECOND)
#define MULTIPLE_512_MASK 0xFFFFFE00
@ -130,6 +132,12 @@ soc_rtc_schedule_one_shot(uint32_t channel, uint32_t ticks)
ti_lib_aon_rtc_channel_enable(channel);
}
/*---------------------------------------------------------------------------*/
rtimer_clock_t
soc_rtc_last_isr_time(void)
{
return last_isr_time;
}
/*---------------------------------------------------------------------------*/
/* The AON RTC interrupt handler */
void
soc_rtc_isr(void)
@ -138,6 +146,8 @@ soc_rtc_isr(void)
ENERGEST_ON(ENERGEST_TYPE_IRQ);
last_isr_time = RTIMER_NOW();
now = ti_lib_aon_rtc_current_compare_value_get();
/* Adjust the s/w tick counter irrespective of which event trigger this */

View file

@ -92,6 +92,8 @@ rtimer_clock_t soc_rtc_get_next_trigger(void);
* instead use Contiki's timer-related libraries
*/
void soc_rtc_schedule_one_shot(uint32_t channel, uint32_t t);
rtimer_clock_t soc_rtc_last_isr_time(void);
/*---------------------------------------------------------------------------*/
#endif /* SOC_RTC_H_ */
/*---------------------------------------------------------------------------*/

@ -1 +1 @@
Subproject commit 63ed52888467ea7d403b0c743852162395232c9e
Subproject commit 6bdb6da3fa9682303799e5c3b1f755398e87fc99

@ -1 +1 @@
Subproject commit 0e82b18bf2c69fb0a40af4d2496db2a3dc721cec
Subproject commit 0270b50ac750f8f3348a98f900a470e7a65ffce8

View file

@ -84,7 +84,7 @@ void
lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
{
lpm_registered_module_t *module;
int i, j;
int i;
uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull |
wake_on;
@ -109,18 +109,6 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
watchdog_periodic();
/* fade away....... */
j = 1000;
for(i = j; i > 0; --i) {
leds_on(LEDS_ALL);
clock_delay_usec(i);
leds_off(LEDS_ALL);
clock_delay_usec(j - i);
}
leds_off(LEDS_ALL);
/* Notify all modules that we're shutting down */
for(module = list_head(modules_list); module != NULL;
module = module->next) {
@ -130,8 +118,10 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on)
}
/* Configure the wakeup trigger */
ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
if(wakeup_pin != IOID_UNUSED) {
ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN);
ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg);
}
/* Freeze I/O latches in AON */
ti_lib_aon_ioc_freeze_enable();
@ -202,8 +192,7 @@ wake_up(void)
/* Remember IRQ energest for next pass */
ENERGEST_IRQ_SAVE(irq_energest);
ENERGEST_ON(ENERGEST_TYPE_CPU);
ENERGEST_OFF(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
/* Sync so that we get the latest values before adjusting recharge settings */
ti_lib_sys_ctrl_aon_sync();
@ -292,7 +281,7 @@ lpm_drop()
if(next_event) {
next_event = next_event - clock_time();
soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() +
soc_rtc_schedule_one_shot(AON_RTC_CH1, soc_rtc_last_isr_time() +
(next_event * (RTIMER_SECOND / CLOCK_SECOND)));
}
@ -396,8 +385,7 @@ lpm_drop()
/* We are only interested in IRQ energest while idle or in LPM */
ENERGEST_IRQ_RESTORE(irq_energest);
ENERGEST_OFF(ENERGEST_TYPE_CPU);
ENERGEST_ON(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
/* Sync the AON interface to ensure all writes have gone through. */
ti_lib_sys_ctrl_aon_sync();
@ -429,8 +417,7 @@ lpm_drop()
void
lpm_sleep(void)
{
ENERGEST_OFF(ENERGEST_TYPE_CPU);
ENERGEST_ON(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
/* We are only interested in IRQ energest while idle or in LPM */
ENERGEST_IRQ_RESTORE(irq_energest);
@ -443,8 +430,7 @@ lpm_sleep(void)
/* Remember IRQ energest for next pass */
ENERGEST_IRQ_SAVE(irq_energest);
ENERGEST_ON(ENERGEST_TYPE_CPU);
ENERGEST_OFF(ENERGEST_TYPE_LPM);
ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
}
/*---------------------------------------------------------------------------*/
void

View file

@ -805,7 +805,7 @@ transmit(unsigned short transmit_len)
cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
/* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
rf_core_cmd_done_en();
rf_core_cmd_done_en(true);
ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
@ -853,6 +853,11 @@ transmit(unsigned short transmit_len)
*/
rf_core_cmd_done_dis();
if(was_off) {
off();
}
return ret;
}
/*---------------------------------------------------------------------------*/
@ -1101,8 +1106,12 @@ off(void)
while(transmitting());
/* stopping the rx explicitly results in lower sleep-mode power usage */
rx_off();
rf_core_power_down();
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
/* Switch HF clock source to the RCOSC to preserve power */
oscillators_switch_to_hf_rc();
@ -1212,6 +1221,12 @@ set_value(radio_param_t param, radio_value_t value)
return RADIO_RESULT_INVALID_VALUE;
}
if(cmd->channel == (uint8_t)value) {
/* We already have that very same channel configured.
* Nothing to do here. */
return RADIO_RESULT_OK;
}
cmd->channel = (uint8_t)value;
break;
case RADIO_PARAM_PAN_ID:

View file

@ -687,7 +687,7 @@ transmit(unsigned short transmit_len)
rx_off_prop();
/* Enable the LAST_COMMAND_DONE interrupt to wake us up */
rf_core_cmd_done_en();
rf_core_cmd_done_en(false);
ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status);
@ -968,6 +968,7 @@ off(void)
return RF_CORE_CMD_OK;
}
rx_off_prop();
rf_core_power_down();
/* Switch HF clock source to the RCOSC to preserve power */

View file

@ -201,6 +201,28 @@ rf_core_wait_cmd_done(void *cmd)
== RF_CORE_RADIO_OP_STATUS_DONE_OK;
}
/*---------------------------------------------------------------------------*/
static int
fs_powerdown(void)
{
rfc_CMD_FS_POWERDOWN_t cmd;
uint32_t cmd_status;
rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_FS_POWERDOWN);
if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
PRINTF("fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
return RF_CORE_CMD_ERROR;
}
if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
PRINTF("fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
cmd_status, cmd.status);
return RF_CORE_CMD_ERROR;
}
return RF_CORE_CMD_OK;
}
/*---------------------------------------------------------------------------*/
int
rf_core_power_up()
{
@ -256,6 +278,9 @@ rf_core_power_down()
if(rf_core_is_accessible()) {
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
/* need to send FS_POWERDOWN or analog components will use power */
fs_powerdown();
}
/* Shut down the RFCORE clock domain in the MCU VD */
@ -378,11 +403,12 @@ rf_core_setup_interrupts()
}
/*---------------------------------------------------------------------------*/
void
rf_core_cmd_done_en()
rf_core_cmd_done_en(bool fg)
{
uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ENABLED_IRQS;
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS +
IRQ_LAST_COMMAND_DONE;
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS | irq;
}
/*---------------------------------------------------------------------------*/
void

View file

@ -331,17 +331,19 @@ uint8_t rf_core_boot(void);
void rf_core_setup_interrupts(void);
/**
* \brief Enable the LAST_CMD_DONE interrupt.
* \brief Enable interrupt on command done.
* \param fg set true to enable irq on foreground command done and false for
* background commands or if not in ieee mode.
*
* This is used within TX routines in order to be able to sleep the CM3 and
* wake up after TX has finished
*
* \sa rf_core_cmd_done_dis()
*/
void rf_core_cmd_done_en(void);
void rf_core_cmd_done_en(bool fg);
/**
* \brief Disable the LAST_CMD_DONE interrupt.
* \brief Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
*
* This is used within TX routines after TX has completed
*

View file

@ -90,6 +90,12 @@ clock_seconds(void)
return seconds;
}
void
clock_set_seconds(unsigned long sec)
{
seconds = sec;
}
void
clock_wait(clock_time_t t)
{

View file

@ -325,6 +325,17 @@ static const int XTAL32_EN = 0;
#define pack_XTAL_CNTL(ctune4pf, ctune, ftune, ibias) \
(*CRM_XTAL_CNTL = ((ctune4pf << 25) | (ctune << 21) | ( ftune << 16) | (ibias << 8) | 0x52))
#define soft_reset() \
__asm__ __volatile__ ( \
"ldr r0, [%[sw]] \n\t" \
"str r0, [%[sw]] \n\t" \
: /* out */ \
: /* in */ \
[sw] "l" (CRM_SW_RST) \
: /* clobber list */ \
"r0", "memory" \
);
#endif /* REG_NO_COMPAT */
#endif

View file

@ -78,5 +78,6 @@ extern nvmErr_t (*nvm_write)(nvmInterface_t nvmInterface, nvmType_t nvmType ,voi
/* SST flash has 32 sectors 4096 bytes each */
/* bit 0 is the first sector, bit 31 is the last */
extern nvmErr_t (*nvm_erase)(nvmInterface_t nvmInterface, nvmType_t nvmType ,uint32_t sectorBitfield);
extern nvmErr_t (*nvm_verify)(nvmInterface_t nvmInterface, nvmType_t nvmType, void *pSrc, uint32_t address, uint32_t numBytes);
extern void(*nvm_setsvar)(uint32_t zero_for_awesome);
#endif //NVM_H

View file

@ -51,6 +51,10 @@ nvmErr_t (*nvm_erase)
(nvmInterface_t nvmInterface, nvmType_t nvmType ,uint32_t sectorBitfield)
= (void*) 0x00006e05;
nvmErr_t (*nvm_verify)
(nvmInterface_t nvmInterface, nvmType_t nvmType, void *pSrc, uint32_t address, uint32_t numBytes)
= (void*) 0x00006f85;
void(*nvm_setsvar)
(uint32_t zero_for_awesome)
= (void *)0x00007085;

View file

@ -35,10 +35,17 @@ endif
CONTIKI_CPU_DIRS = $(CONTIKI_CPU_FAM_DIR) . dev
MSP430 = msp430.c flash.c clock.c leds.c leds-arch.c \
watchdog.c lpm.c mtarch.c rtimer-arch.c
watchdog.c lpm.c rtimer-arch.c
UIPDRIVERS = me.c me_tabs.c slip.c crc16.c
ELFLOADER = elfloader.c elfloader-msp430.c symtab.c
ifndef CPU_HAS_MSP430X
# include mtarch.c only in the non-large memory model case, because
# the current implementation assumes 16-bit addresses (function pointers
# stored as "unsigned short").
MSP430 += mtarch.c
endif
ifeq ($(TARGET_MEMORY_MODEL),large)
ELFLOADER = elfloader-msp430x.c symtab.c
endif

View file

@ -45,6 +45,8 @@ ISR(TIMERB1, cc2420_timerb1_interrupt)
ENERGEST_ON(ENERGEST_TYPE_IRQ);
/* always read TBIV to clear IFG */
tbiv = TBIV;
/* read and discard tbiv to avoid "variable set but not used" warning */
(void)tbiv;
if(CC2420_SFD_IS_1) {
cc2420_sfd_counter++;
cc2420_sfd_start_time = TBCCR1;

View file

@ -44,6 +44,8 @@ ISR(TIMERB1, cc2520_timerb1_interrupt)
ENERGEST_ON(ENERGEST_TYPE_IRQ);
/* always read TBIV to clear IFG */
tbiv = TBIV;
/* read and discard tbiv to avoid "variable set but not used" warning */
(void)tbiv;
if(CC2520_SFD_IS_1) {
cc2520_sfd_counter++;
cc2520_sfd_start_time = TBCCR1;

View file

@ -32,8 +32,12 @@
#include "contiki.h"
#include "dev/watchdog.h"
/* dco_required set to 1 will cause the CPU not to go into
* sleep modes where the DCO clock stopped */
int msp430_dco_required;
#if defined(__MSP430__) && defined(__GNUC__)
#define asmv(arg) __asm__ __volatile__(arg)
#define asmv(arg) __asm__ __volatile__ (arg)
#endif
/*---------------------------------------------------------------------------*/
@ -42,8 +46,8 @@ void *
w_memcpy(void *out, const void *in, size_t n)
{
uint8_t *src, *dest;
src = (uint8_t *) in;
dest = (uint8_t *) out;
src = (uint8_t *)in;
dest = (uint8_t *)out;
while(n-- > 0) {
*dest++ = *src++;
}
@ -56,7 +60,7 @@ void *
w_memset(void *out, int value, size_t n)
{
uint8_t *dest;
dest = (uint8_t *) out;
dest = (uint8_t *)out;
while(n-- > 0) {
*dest++ = value & 0xff;
}
@ -152,10 +156,30 @@ init_ports(void)
/*---------------------------------------------------------------------------*/
/* msp430-ld may align _end incorrectly. Workaround in cpu_init. */
#if defined(__MSP430__) && defined(__GNUC__)
extern int _end; /* Not in sys/unistd.h */
extern int _end; /* Not in sys/unistd.h */
static char *cur_break = (char *)&_end;
#endif
/*---------------------------------------------------------------------------*/
/* add/remove_lpm_req - for requiring a specific LPM mode. currently Contiki */
/* jumps to LPM3 to save power, but DMA will not work if DCO is not clocked */
/* so some modules might need to enter their LPM requirements */
/* NOTE: currently only works with LPM1 (e.g. DCO) requirements. */
/*---------------------------------------------------------------------------*/
void
msp430_add_lpm_req(int req)
{
if(req <= MSP430_REQUIRE_LPM1) {
msp430_dco_required++;
}
}
void
msp430_remove_lpm_req(int req)
{
if(req <= MSP430_REQUIRE_LPM1) {
msp430_dco_required--;
}
}
void
msp430_cpu_init(void)
{
@ -164,7 +188,7 @@ msp430_cpu_init(void)
init_ports();
/* set DCO to a reasonable default value (8MHz) */
msp430_init_dco();
/* calibrate the DCO step-by-step */
/* calibrate the DCO step-by-step */
msp430_sync_dco();
eint();
#if defined(__MSP430__) && defined(__GNUC__)
@ -172,6 +196,7 @@ msp430_cpu_init(void)
cur_break++;
}
#endif
msp430_dco_required = 0;
}
/*---------------------------------------------------------------------------*/
@ -191,7 +216,7 @@ splhigh_(void)
asmv("mov r2, %0" : "=r" (sr));
asmv("bic %0, r2" : : "i" (GIE));
#endif
return sr & GIE; /* Ignore other sr bits. */
return sr & GIE; /* Ignore other sr bits. */
}
/*---------------------------------------------------------------------------*/
/*
@ -209,7 +234,8 @@ splhigh_(void)
/* } */
/*---------------------------------------------------------------------------*/
#ifdef __IAR_SYSTEMS_ICC__
int __low_level_init(void)
int
__low_level_init(void)
{
/* turn off watchdog so that C-init will run */
WDTCTL = WDTPW + WDTHOLD;
@ -224,7 +250,8 @@ int __low_level_init(void)
#endif
/*---------------------------------------------------------------------------*/
void
msp430_sync_dco(void) {
msp430_sync_dco(void)
{
uint16_t oldcapture;
int16_t diff;
/* DELTA_2 assumes an ACLK of 32768 Hz */
@ -260,7 +287,7 @@ msp430_sync_dco(void) {
if(DCOCTL == 0x00) { /* Did DCO roll over? */
BCSCTL1++;
}
/* -> Select next higher RSEL */
/* -> Select next higher RSEL */
}
}

View file

@ -51,6 +51,11 @@ static volatile uint8_t transmitting;
#define TX_WITH_INTERRUPT 1
#endif /* UART0_CONF_TX_WITH_INTERRUPT */
#ifdef UART0_CONF_RX_WITH_DMA
#define RX_WITH_DMA UART0_CONF_RX_WITH_DMA
#else /* UART0_CONF_RX_WITH_DMA */
#define RX_WITH_DMA 1
#endif /* UART0_CONF_RX_WITH_DMA */
#if TX_WITH_INTERRUPT
#define TXBUFSIZE 64
@ -59,6 +64,30 @@ static struct ringbuf txbuf;
static uint8_t txbuf_data[TXBUFSIZE];
#endif /* TX_WITH_INTERRUPT */
#if RX_WITH_DMA
#define RXBUFSIZE 128
static uint8_t rxbuf[RXBUFSIZE];
static uint16_t last_size;
static struct ctimer rxdma_timer;
static void
handle_rxdma_timer(void *ptr)
{
uint16_t size;
size = DMA0SZ; /* Note: loop requires that size is less or eq to RXBUFSIZE */
while(last_size != size) {
uart0_input_handler((unsigned char)rxbuf[RXBUFSIZE - last_size]);
last_size--;
if(last_size == 0) {
last_size = RXBUFSIZE;
}
}
ctimer_reset(&rxdma_timer);
}
#endif /* RX_WITH_DMA */
/*---------------------------------------------------------------------------*/
uint8_t
uart0_active(void)
@ -69,6 +98,9 @@ uart0_active(void)
void
uart0_set_input(int (*input)(unsigned char c))
{
#if RX_WITH_DMA /* This needs to be called after ctimer process is started */
ctimer_set(&rxdma_timer, CLOCK_SECOND / 64, handle_rxdma_timer, NULL);
#endif
uart0_input_handler = input;
}
/*---------------------------------------------------------------------------*/
@ -100,7 +132,7 @@ uart0_writeb(unsigned char c)
#endif /* TX_WITH_INTERRUPT */
}
/*---------------------------------------------------------------------------*/
#if ! NETSTACK_CONF_WITH_IPV4 /* If NETSTACK_CONF_WITH_IPV4 is defined, putchar() is defined by the SLIP driver */
#if !NETSTACK_CONF_WITH_IPV4 /* If NETSTACK_CONF_WITH_IPV4 is defined, putchar() is defined by the SLIP driver */
#endif /* ! NETSTACK_CONF_WITH_IPV4 */
/*---------------------------------------------------------------------------*/
/**
@ -135,8 +167,24 @@ uart0_init(unsigned long ubr)
ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data));
IE2 |= UCA0TXIE; /* Enable UCA0 TX interrupt */
#endif /* TX_WITH_INTERRUPT */
#if RX_WITH_DMA
IE2 &= ~UCA0RXIE; /* disable USART0 RX interrupt */
/* UART0_RX trigger */
DMACTL0 = DMA0TSEL_3;
/* source address = UCA0RXBUF */
DMA0SA = (unsigned int)&UCA0RXBUF;
DMA0DA = (unsigned int)&rxbuf;
DMA0SZ = RXBUFSIZE;
last_size = RXBUFSIZE;
DMA0CTL = DMADT_4 + DMASBDB + DMADSTINCR_3 + DMAEN + DMAREQ;
msp430_add_lpm_req(MSP430_REQUIRE_LPM1);
#endif /* RX_WITH_DMA */
}
/*---------------------------------------------------------------------------*/
#if !RX_WITH_DMA
ISR(USCIAB0RX, uart0_rx_interrupt)
{
uint8_t c;
@ -148,18 +196,19 @@ ISR(USCIAB0RX, uart0_rx_interrupt)
c = UCA0RXBUF;
if(uart0_input_handler != NULL) {
if(uart0_input_handler(c)) {
LPM4_EXIT;
LPM4_EXIT;
}
}
}
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
}
#endif /* !RX_WITH_DMA */
/*---------------------------------------------------------------------------*/
#if TX_WITH_INTERRUPT
ISR(USCIAB0TX, uart0_tx_interrupt)
{
ENERGEST_ON(ENERGEST_TYPE_IRQ);
if((IFG2 & UCA0TXIFG)){
if((IFG2 & UCA0TXIFG)) {
if(ringbuf_elements(&txbuf) == 0) {
transmitting = 0;

View file

@ -14,10 +14,10 @@ NM ?= nm
OBJCOPY ?= objcopy
STRIP ?= strip
ifdef WERROR
CFLAGSWERROR=-Werror -pedantic -std=c99 -Werror
CFLAGSWERROR=-Werror
endif
CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR)
CFLAGS += $(CFLAGSNO) -O
CFLAGS += $(CFLAGSNO)
ifeq ($(HOST_OS),Darwin)
AROPTS = -r
@ -25,7 +25,7 @@ LDFLAGS += -Wl,-flat_namespace
CFLAGS += -DHAVE_SNPRINTF=1 -U__ASSERT_USE_STDERR
else
ifeq ($(HOST_OS),Linux)
LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic
LDFLAGS += -Wl,-Map=contiki-$(TARGET).map,-export-dynamic
endif
endif

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 2013, Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Vladimir Pouzanov <farcaller@gmail.com>
*
*/
#include "contiki.h"
#include "contiki-conf.h"
#if defined(linux) && NETSTACK_CONF_WITH_IPV6
#include "linuxradio-drv.h"
#include "net/packetbuf.h"
#include "net/netstack.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <linux/sockios.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
static int sockfd = -1;
static char *sockbuf;
static int buflen;
#define MAX_PACKET_SIZE 256
static int
init(void)
{
sockbuf = malloc(MAX_PACKET_SIZE);
if(sockbuf == 0) {
return 1;
}
return 0;
}
static int
prepare(const void *payload, unsigned short payload_len)
{
if(payload_len > MAX_PACKET_SIZE) {
return 0;
}
memcpy(sockbuf, payload, payload_len);
buflen = payload_len;
return 0;
}
static int
transmit(unsigned short transmit_len)
{
int sent = 0;
sent = send(sockfd, sockbuf, buflen, 0);
if(sent < 0) {
perror("linuxradio send()");
return RADIO_TX_ERR;
}
buflen = 0;
return RADIO_TX_OK;
}
static int
my_send(const void *payload, unsigned short payload_len)
{
int ret = -1;
if(prepare(payload, payload_len)) {
return ret;
}
ret = transmit(payload_len);
return ret;
}
static int
my_read(void *buf, unsigned short buf_len)
{
return 0;
}
static int
channel_clear(void)
{
return 1;
}
static int
receiving_packet(void)
{
return 0;
}
static int
pending_packet(void)
{
return 0;
}
static int
set_fd(fd_set *rset, fd_set *wset)
{
FD_SET(sockfd, rset);
return 1;
}
static void
handle_fd(fd_set *rset, fd_set *wset)
{
if(FD_ISSET(sockfd, rset)) {
int bytes = read(sockfd, sockbuf, MAX_PACKET_SIZE);
buflen = bytes;
memcpy(packetbuf_dataptr(), sockbuf, bytes);
packetbuf_set_datalen(bytes);
NETSTACK_RDC.input();
}
}
static const struct select_callback linuxradio_sock_callback = { set_fd, handle_fd };
static int
on(void)
{
struct ifreq ifr;
int err;
struct sockaddr_ll sll;
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IEEE802154));
if(sockfd < 0) {
perror("linuxradio socket()");
return 0;
} else {
strncpy((char *)ifr.ifr_name, NETSTACK_CONF_LINUXRADIO_DEV, IFNAMSIZ);
err = ioctl(sockfd, SIOCGIFINDEX, &ifr);
if(err == -1) {
perror("linuxradio ioctl()");
return 0;
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(ETH_P_IEEE802154);
if(bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
perror("linuxradio bind()");
return 0;
}
select_set_callback(sockfd, &linuxradio_sock_callback);
return 1;
}
}
static int
off(void)
{
close(sockfd);
sockfd = -1;
return 1;
}
const struct radio_driver linuxradio_driver =
{
init,
prepare,
transmit,
my_send,
my_read,
channel_clear,
receiving_packet,
pending_packet,
on,
off,
};
#endif

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2013, Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Vladimir Pouzanov <farcaller@gmail.com>
*
*/
#ifndef __LINUXRADIO_DRV_H__
#define __LINUXRADIO_DRV_H__
#include "dev/radio.h"
extern const struct radio_driver linuxradio_driver;
#endif

View file

@ -93,8 +93,11 @@ static void
remove_route(void)
{
char buf[1024];
int ret;
snprintf(buf, sizeof(buf), "route delete -net 172.18.0.0");
system(buf);
ret = system(buf);
fprintf(stderr, "ret %d\n", ret);
fprintf(stderr, "%s\n", buf);
}
@ -103,7 +106,8 @@ void
tapdev_init(void)
{
char buf[1024];
int ret;
fd = open(DEVTAP, O_RDWR);
if(fd == -1) {
perror("tapdev: tapdev_init: open");
@ -123,7 +127,8 @@ tapdev_init(void)
#endif /* Linux */
snprintf(buf, sizeof(buf), "ifconfig tap0 inet 172.18.0.1/16");
system(buf);
ret = system(buf);
fprintf(stderr, "ret %d\n", ret);
fprintf(stderr, "%s\n", buf);
#ifdef linux
/* route add for linux */
@ -132,8 +137,9 @@ tapdev_init(void)
/* route add for freebsd */
snprintf(buf, sizeof(buf), "route add -net 172.18.0.0/16 -iface tap0");
#endif /* linux */
system(buf);
ret = system(buf);
fprintf(stderr, "ret %d\n", ret);
fprintf(stderr, "%s\n", buf);
atexit(remove_route);

View file

@ -331,7 +331,10 @@ tapdev_init(void)
*/
/* freebsd */
snprintf(buf, sizeof(buf), "ifconfig tap0 up");
system(buf);
if(system(buf) == -1) {
perror("tapdev: system: ifconfig");
return;
}
printf("%s\n", buf);
/* */

View file

@ -192,7 +192,7 @@ uint8_t wfall_send(const uip_lladdr_t *lladdr);
static uip_ipaddr_t last_sender;
#endif
static void
static int
output(void)
{
#if FALLBACK_HAS_ETHERNET_HEADERS&&0
@ -203,8 +203,8 @@ output(void)
}
uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr);
#endif
PRINTF("FUT: %u\n", uip_len);
wfall_send(0);
PRINTF("FUT: %u\n", uip_len);
return wfall_send(0);
}
const struct uip_fallback_interface rpl_interface = {

View file

@ -127,7 +127,7 @@ else
STRIP = $(CROSS_COMPILE)strip
ifdef WERROR
CFLAGSWERROR ?= -Werror -pedantic -std=c99 -Werror
CFLAGSWERROR ?= -Werror
endif
CFLAGSNO ?= -Wall -g $(CFLAGSWERROR)

View file

@ -102,12 +102,10 @@ ifeq ($(STM32W_CPUREV), CC)
LD-EXT=-stm32w108CC
RAM_SIZE = 2*8192
FLASH_SIZE = 2*128*1024
${warning "using stm32w108CC specific ld file"}
else ifeq ($(STM32W_CPUREV), xB)
LD-EXT=-stm32w108xB
RAM_SIZE = 8192
FLASH_SIZE = 128*1024
${warning "using stm32w108xB specific ld file"}
else
${error "Bad STM32W_CPUREV value or no STM32W_CPUREV value specified. Cpu revision should be specified. Please read cpu/stm32w108/README.txt for more details."}
endif

View file

@ -72,6 +72,7 @@
#if RDC_CONF_DEBUG_LED
#define LED_RDC RDC_CONF_DEBUG_LED
#undef LED_ACTIVITY
#define LED_ACTIVITY 1
#else
#define LED_RDC 0
@ -117,6 +118,7 @@
#endif /* LED_ACTIVITY */
#if RDC_CONF_HARDWARE_CSMA
#undef MAC_RETRIES
#define MAC_RETRIES 0
#endif /* RDC_CONF_HARDWARE_CSMA */
@ -169,6 +171,7 @@ const RadioTransmitConfig radioTransmitConfig = {
TRUE /* appendCrc; */
};
#undef MAC_RETRIES
#define MAC_RETRIES 0
/*