├── .gitattributes ├── include ├── adc.h ├── debug_uart.h ├── gpio.h ├── uart.h ├── stdlib.h ├── timer.h ├── m25p80_eeprom.h ├── config.h ├── ds3231_rtc.h ├── interrupt.h ├── i2c.h ├── pwmc.h ├── adxl345.h ├── spi.h └── qspi.h ├── LICENSE ├── .gitignore ├── cmake ├── taurusConfig.cmake.in ├── taurusUploader.cmake.in └── taurusToolchain.cmake ├── common ├── mbl.lds ├── rawfloat.c ├── crt.S └── stdlib.c ├── drivers ├── gpio.c ├── timer.c ├── debug_uart.c ├── interrupt.c ├── i2c.c ├── uart.c ├── pwmc.c ├── spi.c └── qspi.c ├── docs ├── getting-started.md └── create-a-project.md ├── CMakeLists.txt ├── README.md ├── setup.sh └── setup.bat /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.bat text eol=crlf 3 | -------------------------------------------------------------------------------- /include/adc.h: -------------------------------------------------------------------------------- 1 | #ifndef ADC_H_ 2 | #define ADC_H_ 3 | 4 | /** 5 | @file adc.h 6 | @brief header file for ADC driver 7 | @detail 8 | */ 9 | 10 | /* Include section 11 | * 12 | ***************************************************/ 13 | 14 | /* Defines section 15 | * 16 | 17 | 18 | ***************************************************/ 19 | 20 | 21 | #include "stdlib.h" //for datatypes 22 | #include "config.h" //for base address 23 | 24 | 25 | 26 | typedef struct 27 | { 28 | UI address_reg; 29 | UI status_reg ; 30 | UI data_reg; 31 | }ADCReg_type; 32 | 33 | 34 | #define A0 0 35 | #define A1 1 36 | #define A2 2 37 | #define A3 3 38 | 39 | #define ADCReg (*((volatile ADCReg_type *)ADC_BASE_ADDRESS)) 40 | 41 | 42 | /* Function declarations 43 | * 44 | ***************************************************/ 45 | 46 | 47 | UI adc_analogRead(UC adc_channel_number); 48 | 49 | 50 | 51 | #endif /* ADC_H_ */ 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Debayan Sutradhar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | Thumbs.db 33 | *.res 34 | /.qmake.cache 35 | /.qmake.stash 36 | CMakeFiles/ 37 | 38 | # qtcreator generated files 39 | *.pro.user* 40 | CMakeLists.txt.user* 41 | 42 | # xemacs temporary files 43 | *.flc 44 | 45 | # Vim temporary files 46 | .*.swp 47 | 48 | # Visual Studio generated files 49 | *.ib_pdb_index 50 | *.idb 51 | *.ilk 52 | *.pdb 53 | *.sln 54 | *.suo 55 | *.vcproj 56 | *vcproj.*.*.user 57 | *.ncb 58 | *.sdf 59 | *.opensdf 60 | *.vcxproj 61 | *vcxproj.* 62 | 63 | # MinGW generated files 64 | *.Debug 65 | *.Release 66 | 67 | # Python byte code 68 | *.pyc 69 | 70 | # Binaries 71 | # -------- 72 | *.dll 73 | *.exe 74 | 75 | # CLion 76 | .idea/ 77 | 78 | # Avra additions -------- 79 | example-test/ 80 | build/ 81 | -------------------------------------------------------------------------------- /cmake/taurusConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Taurus global CMake configuration file 2 | # Auto generated - DO NOT EDIT THIS FILE! 3 | # If you want to change below properties, run Taurus setup script again with appropriate arguments 4 | 5 | set(TAURUS_TARGET_BOARD @TAURUS_TARGET_BOARD@) 6 | set(TAURUS_TARGET_SOC @TAURUS_TARGET_SOC@) 7 | set(TAURUS_TARGET_TRIPLET @TAURUS_TARGET_TRIPLET@) 8 | set(TAURUS_TOOLCHAIN_PATH "@TAURUS_TOOLCHAIN_PATH@") 9 | set(TAURUS_VEGADUDE_PATH "@TAURUS_VEGADUDE_PATH@") 10 | 11 | include("${CMAKE_CURRENT_LIST_DIR}/taurusToolchain.cmake") 12 | include("${CMAKE_CURRENT_LIST_DIR}/taurusTargets.cmake") 13 | set(TAURUS_LIB_INSTALL_DIR ${CMAKE_CURRENT_LIST_DIR}) 14 | 15 | function(configure_taurus_uploader) 16 | set(options START_AFTER_UPLOAD) 17 | set(oneValueArgs EXEC_NAME TARGET_PATH) 18 | set(multiValueArgs VEGADUDE_ARGS) 19 | 20 | cmake_parse_arguments(TAURUS "${options}" "${oneValueArgs}" 21 | "${multiValueArgs}" ${ARGN}) 22 | 23 | if(NOT DEFINED TAURUS_EXEC_NAME) 24 | set(TAURUS_EXEC_NAME ${PROJECT_NAME}) 25 | endif() 26 | 27 | configure_file( 28 | ${TAURUS_LIB_INSTALL_DIR}/taurusUploader.cmake.in 29 | ${CMAKE_CURRENT_BINARY_DIR}/taurusUploader.cmake 30 | @ONLY) 31 | 32 | install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/taurusUploader.cmake") 33 | endfunction() 34 | -------------------------------------------------------------------------------- /include/debug_uart.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Project Name : MDP - Microprocessor Development Project 4 | Project Code : HD083D 5 | Created : 07-Nov-2019 6 | Filename : debug_uart.h 7 | Purpose : Common interface for uart 8 | Description : UART tx/rx functions 9 | Author(s) : Premjith A V, Sreenadh S 10 | Email : premjith@cdac.in 11 | 12 | See LICENSE for license details. 13 | ******************************************************************************/ 14 | /** 15 | @file debug_uart.h 16 | @brief header file for debug_uart 17 | @detail 18 | */ 19 | 20 | #ifndef DEBUG_UART_H_ 21 | #define DEBUG_UART_H_ 22 | 23 | #include "config.h" 24 | #include "stdlib.h" 25 | /** 26 | * Definition section 27 | ***************************************************/ 28 | 29 | typedef struct uart_reg 30 | { 31 | UI UART_DR; /*0x00*/ 32 | UI UART_IE; /*0x04*/ 33 | UI UART_IIR; /*0x08*/ 34 | UI UART_LCR; /*0x0c*/ 35 | UI Dummy10; /*0x10*/ 36 | UI UART_LSR; /*0x14*/ 37 | }UART_REG; 38 | 39 | /** 40 | * Function declaration section 41 | ***************************************************/ 42 | 43 | void init_uart(void); 44 | void tx_uart(UC tx_char); 45 | UC rx_uart(void); 46 | UL get_long_int(UC noofBytes); 47 | UC get_hex(); 48 | UL get_decimal(UC noOfDigits); 49 | 50 | #define uart_regs (*((volatile UART_REG *)(UART_BASE))) 51 | 52 | #endif /* DEBUG_UART_H_ */ 53 | -------------------------------------------------------------------------------- /include/gpio.h: -------------------------------------------------------------------------------- 1 | /** @file gpio.h 2 | * @brief Header file with functions to use GPIO pins. 3 | * 4 | * @author Debayan Sutradhar 5 | * 6 | * SPDX-License-Identifier: MIT 7 | */ 8 | 9 | 10 | 11 | #ifndef GPIO_H 12 | #define GPIO_H 13 | 14 | #define GPIO_0 0 15 | #define GPIO_1 1 16 | #define GPIO_2 2 17 | #define GPIO_3 3 18 | 19 | #define GPIO_4 4 20 | #define GPIO_5 5 21 | #define GPIO_6 6 22 | #define GPIO_7 7 23 | 24 | #define GPIO_8 8 25 | #define GPIO_9 9 26 | #define GPIO_10 10 27 | #define GPIO_11 11 28 | 29 | #define GPIO_12 12 30 | #define GPIO_13 13 31 | #define GPIO_14 14 32 | #define GPIO_15 15 33 | 34 | #define GPIO_16 16 35 | #define GPIO_17 17 36 | #define GPIO_18 18 37 | #define GPIO_19 19 38 | 39 | #define GPIO_20 20 40 | #define GPIO_21 21 41 | #define GPIO_22 22 42 | #define GPIO_23 23 43 | 44 | #define GPIO_24 24 45 | #define GPIO_25 25 46 | #define GPIO_26 26 47 | #define GPIO_27 27 48 | 49 | #define GPIO_28 28 50 | #define GPIO_29 29 51 | #define GPIO_30 30 52 | #define GPIO_31 31 53 | 54 | #define HIGH 1 55 | #define LOW 0 56 | 57 | #define OUT 1 58 | #define IN 0 59 | 60 | 61 | void GPIO_init(); 62 | void GPIO_set_pin_mode(unsigned short pin, unsigned short direction); 63 | unsigned short GPIO_read_pin(unsigned short pin); 64 | void GPIO_write_pin(unsigned short pin, unsigned short data); 65 | //unsigned long long pulse_duration(); 66 | //UL pulse_duration(US GPIO_number, US val); 67 | 68 | 69 | #endif /* GPIO_H */ 70 | -------------------------------------------------------------------------------- /include/uart.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file uart.h 3 | @brief header file for UART driver 4 | @detail 5 | */ 6 | 7 | #ifndef __UART_H 8 | #define __UART_H 9 | 10 | typedef unsigned char UC; //1 Byte 11 | typedef unsigned short US; //2 Bytes 12 | typedef unsigned int UI; //4 Bytes 13 | typedef unsigned long UL; //8 Bytes 14 | 15 | typedef struct 16 | { 17 | UI UART_DR; 18 | UI UART_IE; 19 | UI UART_IIR_FCR; 20 | UI UART_LCR; 21 | UI Dummy; 22 | UI UART_LSR; 23 | } UART_REG_TYPE; 24 | 25 | #define UART_0 0 26 | #define UART_1 1 27 | #define UART_2 2 28 | 29 | #define UART_NO_ERROR 0 30 | #define UART_PARITY_ERROR -1 31 | #define UART_OVERRUN_ERROR -2 32 | #define UART_FRAMING_ERROR -3 33 | 34 | #define TX_ENABLE 1 35 | #define TX_DISABLE 0 36 | #define RX_ENABLE 1 37 | #define RX_DISABLE 0 38 | 39 | #define UartReg(i) (*((volatile UART_REG_TYPE *)(UART_BASE+ (0x100 * i)))) 40 | 41 | void uart_init(UC uart_number); 42 | void uart_configure(UC uart_number, UL Baud_rate, UL frame_value, UL Uart_clock); 43 | void uart_putchar(UC uart_number, UC bTxCharacter, char *error); 44 | UC uart_getchar(UC uart_number, char *error); 45 | UC uart_getchar_async(UC uart_number, char *error); 46 | void uart_intr_enable(UC uart_number, UC tx_intr, UC rx_intr); 47 | void uart_set_baud_rate(UC uart_number,UL Baud_rate, UL Uart_clock); 48 | void uart_intr_enable(UC uart_number, UC tx_intr, UC rx_intr); 49 | void uart_tx_rx(UC TxUart,UC RxUart); 50 | UC uart_getchar_sim_txn_rxn(UC uart_number_tx,UC uart_number_rx, char *error,char txdata); 51 | 52 | #endif /*__UART_H*/ -------------------------------------------------------------------------------- /include/stdlib.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Project Name : MDP - Microprocessor Development Project 4 | Project Code : HD083D 5 | Created : 07-Nov-2019 6 | Filename : stdlib.h 7 | Purpose : Generic library functions 8 | Description : Provides generic library functions like 9 | printf/memcpy etc 10 | Author(s) : Premjith A V 11 | Email : premjith@cdac.in 12 | 13 | See LICENSE for license details. 14 | ******************************************************************************/ 15 | /** 16 | @file stdlib.h 17 | @brief header file for standard library functions 18 | @detail 19 | */ 20 | 21 | #ifndef INCLUDE_STDLIB_H_ 22 | #define INCLUDE_STDLIB_H_ 23 | 24 | #include 25 | 26 | // FIXME: to be removed 27 | typedef unsigned char UC; //1 Byte 28 | typedef unsigned int UI; //4 Bytes 29 | typedef unsigned long UL; //4 Bytes 30 | typedef unsigned short US; //2 Bytes 31 | 32 | /* End of file character. 33 | Some things throughout the library rely on this being -1. */ 34 | #ifndef EOF 35 | # define EOF (-1) 36 | #endif 37 | 38 | int printf(const char* fmt, ...); 39 | int sprintf(char * buffer,const char *fmt, ...); 40 | int putchar(int ch); 41 | int puts(const char *p); 42 | int delay(unsigned int count); 43 | int udelay(unsigned int count); 44 | //void usleep(unsigned int microsec); 45 | int _usleep(unsigned int microsec); 46 | void usleep(unsigned long delay); 47 | int atoi(char *s); 48 | float atof(char* s); 49 | clock_t get_time(); 50 | void *_sbrk(int incr); 51 | 52 | #endif /* INCLUDE_STDLIB_H_ */ 53 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | /** @file timer.h 2 | * @brief Header file with functions to use hardware timers. 3 | * 4 | * @author Debayan Sutradhar 5 | * 6 | * SPDX-License-Identifier: MIT 7 | */ 8 | 9 | 10 | #ifndef TIMER_H 11 | #define TIMER_H 12 | 13 | #include "config.h" 14 | 15 | #define TIMER_0 0 16 | #define TIMER_1 1 17 | #define TIMER_2 2 18 | 19 | typedef struct 20 | { 21 | volatile unsigned int load_count; 22 | volatile unsigned int current_value; 23 | volatile unsigned int control; 24 | volatile unsigned int EOI; 25 | volatile unsigned int interrupt_status; 26 | } TIMER_Type; 27 | 28 | 29 | #define TIMER(n) (*((volatile TIMER_Type *)(TIMER_BASE_ADDRESS + (n * sizeof(TIMER_Type))))) 30 | #define TIMER_acknowledge_interrupt(n) TIMER(n).EOI; 31 | 32 | void TIMER_setup_delay(unsigned char timer, unsigned long clocks); 33 | 34 | #define TIMER_setup_delay_millis(timer, millis, handler) \ 35 | TIMER_setup_delay(timer, (SYSTEM_FREQUENCY * seconds) / 1000) 36 | 37 | #define TIMER_setup_delay_seconds(timer, seconds) \ 38 | TIMER_setup_delay(timer, SYSTEM_FREQUENCY * seconds) 39 | 40 | void TIMER_setup_interrupt(unsigned char timer, unsigned long clocks, void (*handler)()); 41 | 42 | #define TIMER_setup_interrupt_millis(timer, millis, handler) \ 43 | TIMER_setup_interrupt(timer, (SYSTEM_FREQUENCY * seconds) / 1000, handler) 44 | 45 | #define TIMER_setup_interrupt_seconds(timer, seconds, handler) \ 46 | TIMER_setup_interrupt(timer, SYSTEM_FREQUENCY * seconds, handler) 47 | 48 | void TIMER_register_isr(unsigned char timer, void (*timer_isr)()); 49 | void TIMER_enable(unsigned char timer); 50 | void TIMER_disable(unsigned char timer); 51 | 52 | #endif /* TIMER_H */ 53 | -------------------------------------------------------------------------------- /cmake/taurusUploader.cmake.in: -------------------------------------------------------------------------------- 1 | #[[ 2 | SPDX-License-Identifier: MIT 3 | Taurus Uploader 4 | This script uses vegadude utility for uploading 5 | Author : Debayan Sutradhar (@rnayabed) 6 | ]] 7 | 8 | 9 | set(TAURUS_START_AFTER_UPLOAD "@TAURUS_START_AFTER_UPLOAD@") 10 | set(TAURUS_TARGET_BOARD "@TAURUS_TARGET_BOARD@") 11 | set(TAURUS_VEGADUDE_PATH "@TAURUS_VEGADUDE_PATH@") 12 | set(TAURUS_EXEC_NAME "@TAURUS_EXEC_NAME@") 13 | set(TAURUS_TARGET_PATH "@TAURUS_TARGET_PATH@") 14 | set(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@") 15 | set(TAURUS_VEGADUDE_ARGS "@TAURUS_VEGADUDE_ARGS@") 16 | 17 | if(TAURUS_TARGET_PATH STREQUAL "") 18 | message(FATAL_ERROR "TAURUS_TARGET_PATH required") 19 | endif() 20 | 21 | if(TAURUS_VEGADUDE_PATH STREQUAL "") 22 | set(TAURUS_VEGADUDE_FULL_PATH vegadude) 23 | else() 24 | set(TAURUS_VEGADUDE_FULL_PATH ${TAURUS_VEGADUDE_PATH}/vegadude) 25 | endif() 26 | 27 | # Use auto config only if args do not contain manual config args 28 | set(IS_ARGS_MANUAL FALSE) 29 | foreach(EACH_ARG ${TAURUS_VEGADUDE_ARGS}) 30 | if(EACH_ARG MATCHES "^(-s[^a].*|--serial.*|-xbs.*|--xmodem-block-size.*)$") 31 | set(IS_ARGS_MANUAL TRUE) 32 | endif() 33 | endforeach() 34 | 35 | if (NOT IS_ARGS_MANUAL) 36 | if(TAURUS_TARGET_BOARD MATCHES "^ARIES_.*") 37 | list(APPEND TAURUS_VEGADUDE_ARGS --aries) 38 | else() 39 | endif() 40 | endif() 41 | 42 | if(TAURUS_START_AFTER_UPLOAD) 43 | list(APPEND TAURUS_VEGADUDE_ARGS --start-after-upload) 44 | endif() 45 | 46 | list(APPEND TAURUS_VEGADUDE_ARGS --target-path ${TAURUS_TARGET_PATH}) 47 | list(APPEND TAURUS_VEGADUDE_ARGS --binary-path ${CMAKE_BINARY_DIR}/${TAURUS_EXEC_NAME}) 48 | 49 | execute_process(COMMAND 50 | ${TAURUS_VEGADUDE_FULL_PATH} ${TAURUS_VEGADUDE_ARGS} 51 | ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE COMMAND_ERROR_IS_FATAL ANY) 52 | -------------------------------------------------------------------------------- /include/m25p80_eeprom.h: -------------------------------------------------------------------------------- 1 | #ifndef _EEPROM_SPI_H 2 | #define _EEPROM_SPI_H 3 | /** 4 | @file m25p80_eeprom.h 5 | @brief header file for m25p80_eeprom 6 | @detail 7 | */ 8 | /*************************************************** 9 | * Module name: M25P80_spi.h 10 | * 11 | * Copyright 2020 Company CDAC(T). 12 | * All Rights Reserved. 13 | * 14 | * The information contained herein is confidential 15 | * property of Company. The user, copying, transfer or 16 | * disclosure of such information is prohibited except 17 | * by express written agreement with Company. 18 | * 19 | * 20 | * Module Description: 21 | * SPI registers and function declarations 22 | * 23 | ***************************************************/ 24 | 25 | /* Include section 26 | * 27 | ***************************************************/ 28 | 29 | /* Define section 30 | * 31 | * 32 | ***************************************************/ 33 | 34 | 35 | /*************Micron M25P80 Serial Flash************* 36 | *************Embedded Memory Command Set************/ 37 | #define WR_DISABLE_LATCH_SPI_CMD 0x04 38 | #define WR_EN_LATCH_SPI_CMD 0x06 39 | #define BYTE_PAGE_PGM_SPI_CMD 0x02 40 | #define RD_DATA_BYTES_SPI_CMD 0x03 41 | #define RD_STATUS_REG_SPI_CMD 0x05 42 | #define RDID_SPI_CMD 0x83 43 | 44 | /***************************************************/ 45 | 46 | 47 | /* Function declaration section 48 | * 49 | * 50 | ***************************************************/ 51 | 52 | UC memcmp(UC *bWrData, UC *bRdData, UI wDataLength); 53 | void ProgramBytePageSPI(UC spi_number,UL wAddress, UC *pbData,UL wDatalength); 54 | UC ReadStatusRegSPI(UC spi_number); 55 | void ReadDataBytesSPI(UC spi_number,UL wAddress, UC *pbData, UL wDatalength); 56 | void TestSPI_Few_Locations(UC spi_number); 57 | #endif /* _EEPROM_SPI_H */ 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /common/mbl.lds: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Project Name : MDP - Microprocessor Development Project 4 | Project Code : HD083D 5 | Created : 07-Nov-2019 6 | Filename : mbl.lds 7 | Purpose : Linker descriptor 8 | Description : Linker descriptor 9 | Author(s) : Premjith A V 10 | Email : premjith@cdac.in 11 | 12 | See LICENSE for license details. 13 | ******************************************************************************/ 14 | 15 | OUTPUT_ARCH( "riscv" ) 16 | ENTRY(_start) 17 | 18 | /*----------------------------------------------------------------------*/ 19 | /* Sections */ 20 | /*----------------------------------------------------------------------*/ 21 | 22 | SECTIONS 23 | { 24 | 25 | /* . = 0x30000; 26 | .INTERRUPT_isr_sect_0 : { *(.INTERRUPT_isr_sect_0) }*/ 27 | 28 | /* text: test code section */ 29 | . = 0x200000;/*SOC ROM start address*/ 30 | .text.init : { *(.text.init) } 31 | 32 | .text : 33 | { 34 | *(.text) 35 | } 36 | /*.INTERRUPT_isr_sect_0 : { *(.INTERRUPT_isr_sect_0) }*/ 37 | /*. = 0x20000;*//*SOC ROM start address*/ 38 | /* data segment */ 39 | .data : { *(.data) } 40 | 41 | .sdata : { 42 | __global_pointer$ = . + 0x800; 43 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*) 44 | *(.sdata .sdata.* .gnu.linkonce.s.*) 45 | } 46 | 47 | /* bss segment */ 48 | _bss_start = .; 49 | .sbss : { 50 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 51 | *(.scommon) 52 | } 53 | .bss : { *(.bss) } 54 | _bss_end = .; 55 | 56 | /* thread-local data segment */ 57 | .tdata : 58 | { 59 | _tls_data = .; 60 | *(.tdata.begin) 61 | *(.tdata) 62 | *(.tdata.end) 63 | } 64 | .tbss : 65 | { 66 | *(.tbss) 67 | *(.tbss.end) 68 | } 69 | 70 | /* End of uninitalized data segement */ 71 | _end = .; 72 | } 73 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file config.h 3 | @brief header file for hardware configuration registers' 4 | @authors Debayan Sutradhar (@rnayabed), Avra Mitra (@abhra0897) 5 | */ 6 | 7 | #ifndef CONFIG_H 8 | #define CONFIG_H 9 | 10 | /* Special Function Register defs */ 11 | #define _SFR_32(mem_addr) (*(volatile unsigned long *)(mem_addr)) 12 | #define _SFR_16(mem_addr) (*(volatile unsigned short *)(mem_addr)) 13 | #define _SFR_8(mem_addr) (*(volatile unsigned char *)(mem_addr)) 14 | 15 | #define SYSTEM_FREQUENCY 100000000UL 16 | #define UART_BASE 0x10000100UL 17 | #define ADC_BASE_ADDRESS 0x10001000UL 18 | #define SPI_BASE_ADDR(i) (((i) == 0 || (i) == 1) ? 0x10000600UL : 0x10200100UL) 19 | #define I2C_BASE_ADDR 0x10000800UL 20 | 21 | #define GPIO_PORT_0_BASE_ADDRESS 0x10080000UL 22 | #define GPIO_PORT_0_DDR_ADDRESS 0x100C0000UL 23 | #define GPIO_PORT_0_DDR _SFR_16(GPIO_PORT_0_DDR_ADDRESS) 24 | #define GPIO_PORT_0_IO(io_num) _SFR_16(GPIO_PORT_0_BASE_ADDRESS | (1 << (io_num + 2))) 25 | #define GPIO_PORT_0_PIN(pin_num) GPIO_PORT_0_IO(pin_num) 26 | 27 | #define GPIO_PORT_1_BASE_ADDRESS 0x10180000UL 28 | #define GPIO_PORT_1_DDR_ADDRESS 0x101C0000UL 29 | #define GPIO_PORT_1_DDR _SFR_16(GPIO_PORT_1_DDR_ADDRESS) 30 | #define GPIO_PORT_1_IO(io_num) _SFR_16(GPIO_PORT_1_BASE_ADDRESS | (1 << (io_num + 2))) 31 | #define GPIO_PORT_1_PIN(pin_num) GPIO_PORT_1_IO(pin_num) 32 | 33 | #define TIMER_BASE_ADDRESS 0x10000A00UL 34 | #define TIMER_INTR_STATUS_ADDRESS 0x10000AA8UL 35 | #define TIMER_INTR_STATUS _SFR_32(TIMER_INTR_STATUS_ADDRESS) 36 | #define TIMER_INTR_FLAG(timer_num) (TIMER_INTR_STATUS & (1 << (timer_num))) 37 | 38 | #define PWMC_BASE_ADDR 0x10400000UL 39 | 40 | #define PLIC_BASE_ADDRESS 0x20010000UL 41 | #define PLIC_SW_INTR_EN_ADDRESS 0x20010400UL 42 | #define PLIC_SW_INTR_EN _SFR_32(PLIC_SW_INTR_EN_ADDRESS) 43 | 44 | #define CONCATENATE(X) #X 45 | #define CONCAT(X) CONCATENATE(X) 46 | 47 | #endif /* CONFIG_H */ 48 | -------------------------------------------------------------------------------- /include/ds3231_rtc.h: -------------------------------------------------------------------------------- 1 | #ifndef __ds3231_h_ 2 | #define __ds3231_h_ 3 | 4 | /** 5 | @file ds3231_rtc.h 6 | @brief header file for ds3231_rtc 7 | @detail 8 | */ 9 | 10 | #include "i2c.h" 11 | 12 | 13 | 14 | // i2c slave address of the DS3231 chip 15 | #define DS3231_I2C_ADDR_WR 0xD0 16 | #define DS3231_I2C_ADDR_RD 0xD1 17 | 18 | // timekeeping registers 19 | #define DS3231_TIME_CAL_ADDR 0x00 20 | #define DS3231_ALARM1_ADDR 0x07 21 | #define DS3231_ALARM2_ADDR 0x0B 22 | #define DS3231_CONTROL_ADDR 0x0E 23 | #define DS3231_STATUS_ADDR 0x0F 24 | #define DS3231_AGING_OFFSET_ADDR 0x10 25 | #define DS3231_TEMPERATURE_ADDR 0x11 26 | 27 | // control register bits 28 | #define DS3231_CONTROL_A1IE 0x1 /* Alarm 2 Interrupt Enable */ 29 | #define DS3231_CONTROL_A2IE 0x2 /* Alarm 2 Interrupt Enable */ 30 | #define DS3231_CONTROL_INTCN 0x4 /* Interrupt Control */ 31 | #define DS3231_CONTROL_RS1 0x8 /* square-wave rate select 2 */ 32 | #define DS3231_CONTROL_RS2 0x10 /* square-wave rate select 2 */ 33 | #define DS3231_CONTROL_CONV 0x20 /* Convert Temperature */ 34 | #define DS3231_CONTROL_BBSQW 0x40 /* Battery-Backed Square-Wave Enable */ 35 | #define DS3231_CONTROL_EOSC 0x80 /* not Enable Oscillator, 0 equal on */ 36 | 37 | 38 | // status register bits 39 | #define DS3231_STATUS_A1F 0x01 /* Alarm 1 Flag */ 40 | #define DS3231_STATUS_A2F 0x02 /* Alarm 2 Flag */ 41 | #define DS3231_STATUS_BUSY 0x04 /* device is busy executing TCXO */ 42 | #define DS3231_STATUS_EN32KHZ 0x08 /* Enable 32KHz Output */ 43 | #define DS3231_STATUS_OSF 0x80 /* Oscillator Stop Flag */ 44 | 45 | 46 | typedef struct{ 47 | UC sec; /* seconds */ 48 | UC min; /* minutes */ 49 | UC hour; /* hours */ 50 | UC wday; /* day of the week */ 51 | UC mday; /* day of the month */ 52 | UC mon; /* month */ 53 | UC year_s; /* year in short notation*/ 54 | 55 | UC yday; /* day in the year */ 56 | UC isdst; /* daylight saving time */ 57 | 58 | 59 | UI year; /* year */ 60 | #ifdef CONFIG_UNIXTIME 61 | uint32_t unixtime; /* seconds since 01.01.1970 00:00:00 UTC*/ 62 | #endif 63 | }RTC_TIME; 64 | 65 | void i2c_get_rtc_DS3231(UC i2c_num, UC Slave_Address_Wr, 66 | UC Slave_Address_Rd, UC RTC_Address); 67 | void i2c_set_rtc_DS3231(UC i2c_num, UC RTC_Address, UC Slave_Address_Wr); 68 | 69 | 70 | 71 | 72 | UC BcdToDec( UC val ); 73 | UC DecToBcd(UC val); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /include/interrupt.h: -------------------------------------------------------------------------------- 1 | /** @file interrupt.h 2 | * @brief Header file with functions to use interrupts. 3 | * 4 | * @author Debayan Sutradhar (@rnayabed), Avra Mitra (@abhra0897) 5 | * 6 | * SPDX-License-Identifier: MIT 7 | */ 8 | 9 | 10 | 11 | #ifndef _INTERRUPT_H 12 | #define _INTERRUPT_H 13 | 14 | #include "stdlib.h" 15 | #include "encoding.h" 16 | 17 | #if __riscv_xlen == 64 18 | 19 | #define UART_0_IRQ 1 20 | #define UART_1_IRQ 2 21 | #define UART_2_IRQ 3 22 | #define SPI_0_IRQ 6 23 | #define SPI_1_IRQ 7 24 | #define I2C_0_IRQ 8 25 | #define I2C_1_IRQ 9 26 | #define TIMER_0_IRQ 10 27 | #define TIMER_1_IRQ 11 28 | #define TIMER_2_IRQ 12 29 | #define GPIO_0_IRQ 20 30 | #define GPIO_1_IRQ 21 31 | #define GPIO_2_IRQ 22 32 | #define GPIO_3_IRQ 23 33 | #define GPIO_4_IRQ 24 34 | #define GPIO_5_IRQ 25 35 | #define GPIO_6_IRQ 26 36 | #define GPIO_7_IRQ 27 37 | #define GPIO_8_IRQ 28 38 | #define GPIO_9_IRQ 29 39 | #define GPIO_10_IRQ 30 40 | #define GPIO_11_IRQ 31 41 | #define GPIO_12_IRQ 32 42 | #else 43 | 44 | #define UART_0_IRQ 0 45 | #define UART_1_IRQ 1 46 | #define UART_2_IRQ 2 47 | #define SPI_0_IRQ 3 48 | #define SPI_1_IRQ 4 49 | #define I2C_0_IRQ 5 50 | #define I2C_1_IRQ 6 51 | #define TIMER_0_IRQ 7 52 | #define TIMER_1_IRQ 8 53 | #define TIMER_2_IRQ 9 54 | #define GPIO_0_IRQ 10 55 | #define GPIO_1_IRQ 11 56 | #define GPIO_2_IRQ 12 57 | #define GPIO_3_IRQ 13 58 | #define GPIO_4_IRQ 14 59 | #define GPIO_5_IRQ 15 60 | #define GPIO_6_IRQ 16 61 | #define GPIO_7_IRQ 17 62 | #define GPIO_8_IRQ 18 63 | #define GPIO_9_IRQ 19 64 | #define GPIO_10_IRQ 20 65 | #define GPIO_11_IRQ 21 66 | #define GPIO_12_IRQ 22 67 | 68 | 69 | #endif 70 | 71 | typedef struct 72 | { 73 | #if __riscv_xlen == 64 74 | UL RAW_INTR; //0x00 75 | UL INTR_EN; //0x08 76 | UL INTR_STATUS; //0x10 77 | #else 78 | UI RAW_INTR; //0x00 79 | UI pad1; //0x04 80 | UI INTR_EN; //0x08 81 | UI pad2; //0x0c 82 | UI INTR_STATUS; //0x10 83 | #endif 84 | } INTR_Type; 85 | 86 | #define PLIC_INTR_REGS (*((volatile INTR_Type *)PLIC_BASE_ADDRESS)) 87 | 88 | 89 | void enable_irq(void); 90 | void enable_sw_irq(void) ; 91 | void interrupt_enable(UC intr_number); 92 | void irq_register_handler(UC irq_no, void (*irq_handler)()); 93 | void sw_irq_register_handler( void (*irq_handler)()); 94 | //void interrupt_handler(void); 95 | void interrupt_handler(void); 96 | void sw_interrupt_handler(void); 97 | void generate_sw_irq(void); 98 | void disable_sw_irq(void); 99 | #endif /* _INTERRUPT_H */ 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /include/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef __I2C_H 2 | #define __I2C_H 3 | /*************************************************** 4 | 5 | 6 | Project Name : MDP - Microprocessor Development Project 7 | Project Code : HD083D 8 | Created : 08-Nov-2019 9 | Filename : i2c.h 10 | Purpose : I2C Firmware header file 11 | Description : I2C functions 12 | Author(s) : Karthika P 13 | Email : karthikap@cdac.in 14 | 15 | See LICENSE for license details. 16 | ***************************************************/ 17 | /** 18 | @file i2c.h 19 | @brief header file for I2C interface 20 | @detail Includes software functions declarations to initialize, 21 | configure, write and read over I2C interface 22 | */ 23 | #include "config.h" 24 | 25 | typedef unsigned char UC; //1 Byte 26 | typedef unsigned short US; //2 Bytes 27 | typedef unsigned int UI; //4 Bytes 28 | typedef unsigned long UL; //8 Bytes 29 | 30 | typedef struct { 31 | UC I2C_CR; 32 | UC I2C_SR0; 33 | UC I2C_SR1; 34 | UC I2C_IER; 35 | UC I2C_TxFF; 36 | UC I2C_RxFF; 37 | UC I2C_CHL; 38 | UC I2C_CHH; 39 | UC I2C_CHHL; 40 | UC I2C_CHHH; 41 | UC I2C_TXCLR; 42 | } I2C_REG_TYPE; 43 | 44 | 45 | #define I2C_0 0 46 | #define I2C_1 1 47 | #define I2C_ADC 8 // at address 0x1000_1000 48 | 49 | 50 | #define I2C_READ 1 51 | #define I2C_WRITE 0 52 | 53 | #define I2C_EEPROM_ADDR_WR (0xA2) 54 | #define I2C_EEPROM_ADDR_RD (0xA3) 55 | 56 | 57 | //Register address mapping 58 | #define I2CReg(i) (*((volatile I2C_REG_TYPE *)(I2C_BASE_ADDR+ (0x100 * i)))) 59 | 60 | 61 | /* Function declaration section 62 | * 63 | ***************************************************/ 64 | 65 | void i2c_initialize(UC i2c_number); 66 | UC i2c_start(UC i2c_number, UC read_length, UC Read); 67 | void i2c_configure(UC i2c_number,UL System_Clock, UL I2C_Clock); 68 | UC i2c_data_write(UC i2c_number, UC *write_data, UC write_length); 69 | void i2c_stop(UC i2c_number); 70 | UC i2c_data_read(UC i2c_number, UC *read_data, UC read_length); 71 | int I2C_intr_handler(UC I2C_number); 72 | void I2C_enable_intr(UC i2c_number,UC tx_intr,UC rx_intr); 73 | 74 | void i2c_WriteByte_EEPROM(UC i2c_number,UC WBdata, US Word_Address, UC Slave_Address_Wr); 75 | UC i2c_ReadByte_EEPROM(UC i2c_number,UC Slave_Address_Wr,UC Slave_Address_Rd, US Word_Address); 76 | void i2c_WriteMultiByte_EEPROM(UC i2c_num, UC *WBdata, US Word_Address,UC Slave_Address_Wr, UC write_data_length); 77 | void i2c_ReadMultiByte_EEPROM(UC i2c_num, UC *rxd_data, UC Slave_Address_Wr,UC Slave_Address_Rd, US Word_Address, UC read_data_length); 78 | 79 | void i2c_WriteByte_SSD1306(UC i2c_number,UC WBdata, US Word_Address, UC Slave_Address_Wr); 80 | UC i2c_ReadByte_SSD1306(UC i2c_number,UC Slave_Address_Wr,UC Slave_Address_Rd, US Word_Address); 81 | void i2c_WriteMultiByte_SSD1306(UC i2c_num, UC *WBdata, US Word_Address,UC Slave_Address_Wr, UC write_data_length); 82 | void i2c_ReadMultiByte_SSD1306(UC i2c_num, UC *rxd_data, UC Slave_Address_Wr,UC Slave_Address_Rd, US Word_Address, UC read_data_length); 83 | 84 | 85 | 86 | #endif /*__I2C_H*/ 87 | 88 | -------------------------------------------------------------------------------- /drivers/gpio.c: -------------------------------------------------------------------------------- 1 | /** @file gpio.c 2 | * @brief Contains functions to use GPIO pins. 3 | * 4 | * @author Debayan Sutradhar 5 | * 6 | * SPDX-License-Identifier: MIT 7 | */ 8 | 9 | 10 | #include "gpio.h" 11 | #include "config.h" 12 | 13 | 14 | /** @fn void GPIO_init(void) 15 | * @brief Initialises GPIO pins. 16 | * 17 | * Initialises GPIO Pins as OUTPUT LOW. 18 | * On Aries v2.0, pins 22, 23, 24 are set 19 | * to HIGH as they are built-in active-low LEDs. 20 | */ 21 | void GPIO_init(void) 22 | { 23 | // Set all pins as output 24 | GPIO_PORT_0_DDR = 0xffff; 25 | GPIO_PORT_1_DDR = 0xffff; 26 | 27 | #ifdef TARGET_BOARD_ARIES_V2 28 | // On Aries v2.0, set built-in active-low LEDs as HIGH 29 | GPIO_PORT_1_IO(6) = 1 << 6; 30 | GPIO_PORT_1_IO(7) = 1 << 7; 31 | GPIO_PORT_1_IO(8) = 1 << 8; 32 | #endif 33 | } 34 | 35 | 36 | /** @fn void GPIO_set_pin_mode(unsigned short pin, unsigned short direction) 37 | * @brief Set data direction of pin. 38 | * @param pin GPIO pin. 39 | * @param direction Direction of the pin. 40 | */ 41 | void GPIO_set_pin_mode(unsigned short pin, unsigned short direction) 42 | { 43 | int adr; 44 | 45 | if (pin >= 16) 46 | { 47 | if (direction == IN) 48 | GPIO_PORT_1_DDR &= ~(1 << pin); 49 | else 50 | GPIO_PORT_1_DDR |= (1 << pin); 51 | } 52 | else 53 | { 54 | if (direction == IN) 55 | GPIO_PORT_0_DDR &= ~(1 << pin); 56 | else 57 | GPIO_PORT_0_DDR |= (1 << pin); 58 | } 59 | 60 | __asm__ __volatile__ ("fence"); 61 | } 62 | 63 | 64 | /** @fn int GPIO_read_pin(unsigned short pin) 65 | * @brief Read GPIO pin value. 66 | * @param pin GPIO pin. 67 | * @return Value read from the pin. 68 | */ 69 | unsigned short GPIO_read_pin(unsigned short pin) 70 | { 71 | if (pin >= 16) 72 | { 73 | pin -= 16; 74 | return GPIO_PORT_1_IO(pin); 75 | } 76 | else 77 | { 78 | return GPIO_PORT_0_IO(pin); 79 | } 80 | } 81 | 82 | 83 | /** @fn void GPIO_write_pin(unsigned short pin, unsigned short data) 84 | * @brief Write value to GPIO pin. 85 | * @param pin GPIO pin. 86 | * @param data Data to be written to pin. 87 | */ 88 | void GPIO_write_pin(unsigned short pin, unsigned short data) 89 | { 90 | if (pin >= 16) 91 | { 92 | pin -= 16; 93 | GPIO_PORT_1_IO(pin) = (data << pin); 94 | } 95 | else 96 | { 97 | GPIO_PORT_0_IO(pin) = (data << pin); 98 | } 99 | __asm__ __volatile__ ("fence"); 100 | } 101 | 102 | /** @fn unsigned long long pulse_duration(unsigned short pin, unsigned short value) 103 | * @brief Reads pulse from a GPIO pin. 104 | * @param pin GPIO pin. 105 | * @param pin value value to pulse on. 106 | */ 107 | /*unsigned long long pulse_duration(US pin_number, US val) 108 | { 109 | clock_t start_time=0, end_time=0; 110 | UL total_time=0; 111 | while(GPIO_read_pin(pin_number)!=val); 112 | start_time = get_time(); 113 | while(GPIO_read_pin(pin_number)==val); 114 | end_time = get_time(); 115 | 116 | total_time = (end_time - start_time)*0.025; 117 | return total_time; 118 | }*/ 119 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Prerequisites 4 | 5 | #### **All of the following prerequisites must be available in your PATH.** 6 | 7 | - [CMake](https://cmake.org/) 8 | - RISC-V GNU Toolchain (Newlib) with support for `rv32im`. 9 | - For Windows, you can use [this prebuilt toolchain](https://gnutoolchains.com/risc-v/). 10 | - For Linux, you can use [this prebuilt toolchain](https://github.com/stnolting/riscv-gcc-prebuilt) or refer to your distribution's repositories. 11 | - [vegadude](https://github.com/rnayabed/vegadude.git). Grab the latest release [here](https://github.com/rnayabed/vegadude/releases/latest). This is the uploader tool to upload your program to your Aries development board. It let's you upload your program directly from cmake via `cmake --install` without having to use a 3rd party terminal. 12 | - [Ninja](https://ninja-build.org/) **: For Windows Only. Linux systems do not require this.** 13 | 14 | ## Terminal emulator 15 | 16 | For terminal, minicom is recommended on Linux. 17 | Taurus creates a minicom configuration for aries boards by default for ease of use, which you can access by simply running `sudo minicom aries`. 18 | 19 | You can also choose to use a different terminal emulator. 20 | 21 | CDAC Aries boards use the following configuration: 22 | 23 | | Property | Value | 24 | |-----------|--------| 25 | | Parity | No | 26 | | Stop bits | 1 | 27 | | RTS/CTS | 0 | 28 | | Bits | 8 | 29 | | Baud rate | 115200 | 30 | 31 | ## Steps 32 | 33 | - Download and extract the [latest release of Taurus](https://github.com/rnayabed/taurus/releases/latest). 34 | - On Windows, run: 35 | ``` 36 | setup.bat --target-triplet --target-board 37 | ``` 38 | 39 | **Run the commmand prompt as Administrator if you want to install Taurus SDK in the default directory (`C:\Program Files (x86)\taurus`). 40 | You can use `--install-path ` to specify where you would like to install.** 41 | - On Linux, run: 42 | ``` 43 | ./setup.sh --target-triplet --target-board 44 | ``` 45 | 46 | - ``: Target triplet from the RISC-V GNU Toolchain. 47 | If you are using a prebuilt toolchain, go to your toolchain directory, there will be a folder with the format `riscv64--elf`. For example, `riscv64-unknown-elf`. 48 | - ``: This is the board you are using. 49 | Available options are: `ARIES_V2`, `ARIES_V3`, `ARIES_MICRO_V1`, `ARIES_IOT_V1`. 50 | - If you are using a different board, you can also use the option `--target-soc` and specify the SoC name. 51 | Available options are: `THEJAS32`, `THEJAS64` and `CDACFPGA`. 52 | - The setup script offers a lot of fine tunable options. you can run the script `--help` for detailed usage. 53 | 54 | ## Finishing Up 55 | 56 | After running the script, you will be greeted with a success message. 57 | If you are using Linux, it will also create a minicom configuration for ease of use. You can skip this by running the setup script with `--no-minicom` 58 | 59 | If you are getting errors, please create a [GitHub issue](https://github.com/rnayabed/taurus/issues/new). 60 | 61 | Otherwise, you can proceed to [create project using Taurus](https://github.com/rnayabed/taurus/blob/master/docs/create-a-project.md), or compiling and uploading [examples](https://github.com/rnayabed/taurus-examples.git). 62 | -------------------------------------------------------------------------------- /include/pwmc.h: -------------------------------------------------------------------------------- 1 | #ifndef _PWMC_H 2 | #define _PWMC_H 3 | /** 4 | @file pwmc.h 5 | @brief header file for PWMC driver 6 | @detail 7 | */ 8 | 9 | /* Include section 10 | * 11 | * 12 | ***************************************************/ 13 | 14 | #include "stdlib.h" //for datatypes 15 | #include "config.h" //for base address 16 | 17 | #define LOW 0 18 | #define HIGH 1 19 | 20 | #define PWM_CH_0 0 21 | #define PWM_CH_1 1 22 | #define PWM_CH_2 2 23 | #define PWM_CH_3 3 24 | #define PWM_CH_4 4 25 | #define PWM_CH_5 5 26 | #define PWM_CH_6 6 27 | #define PWM_CH_7 7 28 | 29 | #define REPEAT_COUNT 5 30 | 31 | #define PWM_IDLE_MODE (0) 32 | #define PWM_ONE_SHORT_MODE (1) 33 | #define PWM_CONTINUOUS_MODE (2) 34 | 35 | #define PWM_LEFT_ALIGN (0) 36 | #define PWM_RIGHT_ALIGN (1) 37 | 38 | #define PWM_LOC_INTR_DIS (0) 39 | #define PWM_LOC_INTR_EN (1) 40 | 41 | #define PWM_OPC_LOW (0) 42 | #define PWM_OPC_HIGH (1) 43 | 44 | #define PWM_REPEAT_COUNT (REPEAT_COUNT) 45 | 46 | #define PWM_GPE (1<<0) 47 | #define PWM_GIE (1<<1) 48 | 49 | 50 | 51 | typedef struct 52 | { 53 | 54 | union 55 | { 56 | struct 57 | { 58 | UI Mode : 2, 59 | AC : 2, 60 | IE : 1, 61 | OPC : 1, 62 | RepeatCount : 16, 63 | Rsvd : 10; 64 | }__attribute__((packed)) Bits; 65 | UI word; 66 | }Control; //0x00 67 | UI Status; //0x04 68 | UI Period; //0x08 69 | UI On_Off; //0x0c 70 | }PWMCregType; 71 | 72 | 73 | 74 | typedef union 75 | { 76 | struct 77 | { 78 | UI Mode : 2, 79 | AC : 2, 80 | IE : 1, 81 | OPC : 1, 82 | RepeatCount : 16, 83 | Rsvd : 10; 84 | }Bits; 85 | UI Value; 86 | }PWMcntrlRegType; 87 | 88 | 89 | #define PWMC_GCR_REG (PWMC_BASE_ADDR + 0x80) 90 | #define PWMCreg(n) (*((volatile PWMCregType *)(PWMC_BASE_ADDR + (n * 0x10)))) 91 | 92 | 93 | /* Function declaration section 94 | * 95 | * 96 | * 97 | ***************************************************/ 98 | void PWMC_Set_Period(UC channel_no, UI period); 99 | void PWMC_Set_OnOffTime(UC channel_no, UI time); 100 | void PWMC_init(UC channel_no,UC mode,UC align,UC intr_en_dis,UC opc, US repeatCount); 101 | void PWMC_Set_mode(UC channel_no,UC mode); 102 | void PWMC_Set_alignment(UC channel_no,UC align); 103 | void PWMC_Set_RepeatCount(UC channel_no,US repeatCount); 104 | void PWMC_Change_mode(void); 105 | void PWMC_Enable(void); 106 | void PWMC_Enable_with_intr(void); 107 | void PWMC_Disable(void); 108 | void pwmc_register_isr(UC pwmc_ch_number,void (*pwmc_isr)()); 109 | void pwmc_ch0_intr_handler(void); 110 | void pwmc_ch1_intr_handler(void); 111 | void pwmc_ch2_intr_handler(void); 112 | void pwmc_ch3_intr_handler(void); 113 | void pwmc_ch4_intr_handler(void); 114 | void pwmc_ch5_intr_handler(void); 115 | void pwmc_ch6_intr_handler(void); 116 | void pwmc_ch7_intr_handler(void); 117 | void gen_LeftAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period); 118 | void gen_RightAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period); 119 | void gen_LeftAlign_PWM_OneShort_Mode(UC channel_no,UI on_time,US repeatCount,UI period); 120 | void gen_RightAlign_PWM_OneShort_Mode(UC channel_no,UI off_time,US repeatCount,UI period); 121 | UC pwm_idle_check_opc(UC channel_no); 122 | #endif /* _PWMC_H */ 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /cmake/taurusToolchain.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | SPDX-License-Identifier: MIT 3 | CMake project toolchain configurator 4 | Author : Debayan Sutradhar (@rnayabed) 5 | ]] 6 | 7 | 8 | # Check Target Board 9 | if (TAURUS_TARGET_BOARD STREQUAL "ARIES_V2") 10 | add_compile_definitions(TARGET_BOARD_ARIES_V2) 11 | set(TAURUS_TARGET_SOC THEJAS32) 12 | elseif (TAURUS_TARGET_BOARD STREQUAL "ARIES_V3") 13 | add_compile_definitions(TARGET_BOARD_ARIES_V3) 14 | set(TAURUS_TARGET_SOC THEJAS32) 15 | elseif (TAURUS_TARGET_BOARD STREQUAL "ARIES_MICRO_V1") 16 | add_compile_definitions(TARGET_BOARD_ARIES_MICRO_V1) 17 | set(TAURUS_TARGET_SOC THEJAS32) 18 | elseif (TAURUS_TARGET_BOARD STREQUAL "ARIES_IOT_V1") 19 | add_compile_definitions(TARGET_BOARD_ARIES_IOT_V1) 20 | set(TAURUS_TARGET_SOC THEJAS32) 21 | elseif(TAURUS_TARGET_BOARD) 22 | message(FATAL_ERROR "Invalid TAURUS_TARGET_BOARD specified") 23 | endif() 24 | 25 | 26 | 27 | # Check Target SoC 28 | if(TAURUS_TARGET_SOC STREQUAL "THEJAS32") 29 | add_compile_definitions(TARGET_SOC_THEJAS32) 30 | set(RISCV_ARCH rv32im) 31 | set(RISCV_ABI ilp32) 32 | elseif(TAURUS_TARGET_SOC STREQUAL "THEJAS64") 33 | add_compile_definitions(TARGET_SOC_THEJAS64) 34 | set(RISCV_ARCH rv64ima) 35 | set(RISCV_ABI lp64) 36 | elseif(TAURUS_TARGET_SOC STREQUAL "CDACFPGA") 37 | add_compile_definitions(TARGET_SOC_CDACFPGA) 38 | set(RISCV_ARCH rv64imafd) 39 | set(RISCV_ABI lp64d) 40 | else() 41 | message(FATAL_ERROR "Invalid TAURUS_TARGET_SOC specified") 42 | endif() 43 | 44 | set(RISCV_CMODEL medany) 45 | 46 | 47 | 48 | # Check target triplet 49 | if(NOT DEFINED TAURUS_TARGET_TRIPLET OR TAURUS_TARGET_TRIPLET STREQUAL "") 50 | message(FATAL_ERROR "TAURUS_TARGET_TRIPLET required") 51 | endif() 52 | 53 | 54 | 55 | # Configure toolchain path if provided 56 | if (DEFINED TAURUS_TOOLCHAIN_PATH AND NOT TAURUS_TOOLCHAIN_PATH STREQUAL "") 57 | set(TAURUS_TOOLCHAIN_FULL_PATH ${TAURUS_TOOLCHAIN_PATH}/bin/${TAURUS_TARGET_TRIPLET}) 58 | else() 59 | set(TAURUS_TOOLCHAIN_FULL_PATH ${TAURUS_TARGET_TRIPLET}) 60 | endif() 61 | 62 | 63 | 64 | # Configure executable suffix for Windows 65 | if (CMAKE_HOST_WIN32) 66 | set(CMAKE_EXECUTABLE_SUFFIX .exe) 67 | endif() 68 | 69 | 70 | 71 | # Configure toolchain 72 | set(CMAKE_SYSTEM_NAME Generic) 73 | set(CMAKE_SYSTEM_PROCESSOR riscv) 74 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 75 | 76 | set(CMAKE_AR ${TAURUS_TOOLCHAIN_FULL_PATH}-ar${CMAKE_EXECUTABLE_SUFFIX}) 77 | set(CMAKE_ASM_COMPILER ${TAURUS_TOOLCHAIN_FULL_PATH}-gcc${CMAKE_EXECUTABLE_SUFFIX}) 78 | set(CMAKE_C_COMPILER ${TAURUS_TOOLCHAIN_FULL_PATH}-gcc${CMAKE_EXECUTABLE_SUFFIX}) 79 | set(CMAKE_CXX_COMPILER ${TAURUS_TOOLCHAIN_FULL_PATH}-g++${CMAKE_EXECUTABLE_SUFFIX}) 80 | set(CMAKE_LINKER ${TAURUS_TOOLCHAIN_FULL_PATH}-ld${CMAKE_EXECUTABLE_SUFFIX}) 81 | set(CMAKE_OBJCOPY ${TAURUS_TOOLCHAIN_FULL_PATH}-objcopy${CMAKE_EXECUTABLE_SUFFIX}) 82 | set(CMAKE_RANLIB ${TAURUS_TOOLCHAIN_FULL_PATH}-ranlib${CMAKE_EXECUTABLE_SUFFIX}) 83 | set(CMAKE_SIZE ${TAURUS_TOOLCHAIN_FULL_PATH}-size${CMAKE_EXECUTABLE_SUFFIX}) 84 | set(CMAKE_STRIP ${TAURUS_TOOLCHAIN_FULL_PATH}-strip${CMAKE_EXECUTABLE_SUFFIX}) 85 | 86 | 87 | 88 | # Search includes and packages in toolchain 89 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 90 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 91 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 92 | -------------------------------------------------------------------------------- /common/rawfloat.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Project Name : MDP - Microprocessor Development Project 4 | Project Code : HD083D 5 | Created : 07-Nov-2019 6 | Filename : rawfloat.c 7 | Purpose : Generic library functions 8 | Description : Provides generic library functions like 9 | printf/memcpy etc 10 | Author(s) : Premjith A V 11 | Email : premjith@cdac.in 12 | 13 | See LICENSE for license details. 14 | ******************************************************************************/ 15 | 16 | /** 17 | @file rawfloat.c 18 | @brief Contains routines for floating point conversions 19 | @detail 20 | */ 21 | 22 | double modf(double value, register double * iptr); 23 | 24 | #define CVTBUFSIZE 80 25 | static char CVTBUF[CVTBUFSIZE]; 26 | /** 27 | @fn static char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag) 28 | @brief To convert a floating point value to ascii string 29 | @param[in] double arg 30 | @param[in] int ndigits 31 | @param[in] int *decpt 32 | @param[in] int *sign 33 | @param[in] char *buf 34 | @param[in] int eflag 35 | @param[Out] No ouput parameter. 36 | @return Pointer to converted string 37 | 38 | */ 39 | static char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag) 40 | { 41 | int r2; 42 | double fi, fj; 43 | volatile char *p, *p1; 44 | 45 | if (ndigits < 0) ndigits = 0; 46 | if (ndigits >= CVTBUFSIZE - 1) ndigits = CVTBUFSIZE - 2; 47 | r2 = 0; 48 | *sign = 0; 49 | p = &buf[0]; 50 | if (arg < 0) 51 | { 52 | *sign = 1; 53 | arg = -arg; 54 | } 55 | arg = modf(arg, &fi); 56 | p1 = &buf[CVTBUFSIZE]; 57 | 58 | if (fi != 0) 59 | { 60 | p1 = &buf[CVTBUFSIZE]; 61 | while (fi != 0) 62 | { 63 | fj = modf(fi / 10, &fi); 64 | *--p1 = (int)((fj + .03) * 10) + '0'; 65 | r2++; 66 | } 67 | while (p1 < &buf[CVTBUFSIZE]) *p++ = *p1++; 68 | } 69 | else if (arg > 0) 70 | { 71 | while ((fj = arg * 10) < 1) 72 | { 73 | arg = fj; 74 | r2--; 75 | } 76 | } 77 | p1 = &buf[ndigits]; 78 | if (eflag == 0) p1 += r2; 79 | *decpt = r2; 80 | if (p1 < &buf[0]) 81 | { 82 | buf[0] = '\0'; 83 | return buf; 84 | } 85 | while (p <= p1 && p < &buf[CVTBUFSIZE]) 86 | { 87 | arg *= 10; 88 | arg = modf(arg, &fj); 89 | *p++ = (int) fj + '0'; 90 | } 91 | if (p1 >= &buf[CVTBUFSIZE]) 92 | { 93 | buf[CVTBUFSIZE - 1] = '\0'; 94 | return buf; 95 | } 96 | p = p1; 97 | *p1 += 5; 98 | while (*p1 > '9') 99 | { 100 | *p1 = '0'; 101 | if (p1 > buf) 102 | ++*--p1; 103 | else 104 | { 105 | *p1 = '1'; 106 | (*decpt)++; 107 | if (eflag == 0) 108 | { 109 | if (p > buf) *p = '0'; 110 | p++; 111 | } 112 | } 113 | } 114 | *p = '\0'; 115 | return buf; 116 | } 117 | 118 | char *ecvt(double arg, int ndigits, int *decpt, int *sign) 119 | { 120 | return cvt(arg, ndigits, decpt, sign, CVTBUF, 1); 121 | } 122 | 123 | char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) 124 | { 125 | return cvt(arg, ndigits, decpt, sign, buf, 1); 126 | } 127 | 128 | char *fcvt(double arg, int ndigits, int *decpt, int *sign) 129 | { 130 | return cvt(arg, ndigits, decpt, sign, CVTBUF, 0); 131 | } 132 | 133 | char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) 134 | { 135 | return cvt(arg, ndigits, decpt, sign, buf, 0); 136 | } 137 | 138 | -------------------------------------------------------------------------------- /drivers/timer.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | /** 4 | @file timer.c 5 | @brief Contains routines for different timer funtions 6 | @detail 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | /** @fn unsigned char TIMER_setup_delay(unsigned char timer, unsigned long clocks) 16 | @brief load, enable and wait for interrupt (Polling mode). 17 | @details The selected timer is loaded with the no of clocks and it is enabled with intr masked. 18 | The timer module waits untill it interrupts. 19 | 20 | @param[in] unsigned short timer: Selected timer, unsigned long clocks: Number of clock ticks to wait 21 | @param[Out] No output parameter. 22 | */ 23 | void TIMER_setup_delay(unsigned char timer, unsigned long clocks) 24 | { 25 | TIMER(timer).control = 0x0; // Disable timer. 26 | TIMER(timer).load_count = clocks / 2; // Load timer with no of clocks. 27 | TIMER(timer).control = 0x7; // Enable timer with intr masked (0111) 28 | 29 | __asm__ __volatile__ ("fence"); 30 | 31 | while(!TIMER_INTR_FLAG(timer)); // Wait till timer interrupts. 32 | TIMER(timer).control = 0x0; // Disable timer. 33 | 34 | __asm__ __volatile__ ("fence"); 35 | } 36 | 37 | 38 | /** @fn void TIMER_setup_interrupt(unsigned char timer, unsigned long clocks, void (*handler)()) 39 | @brief Enable timer interrupt in unmasked & user defined mode.. 40 | @details The selected timer's interrupt is enabled. 41 | The LoadCount will be reloaded with no_of_clocks once the timer is expired and if timer is not disabled. 42 | 43 | @param[in] unsigned char timer: Selected timer, unsigned int no_of_clocks : value to be loaded to LoadCount register 44 | @param[Out] No output parameter. 45 | */ 46 | void TIMER_setup_interrupt(unsigned char timer, unsigned long clocks, 47 | void (*handler)(void)) 48 | { 49 | unsigned char irq_no = 7; 50 | #if __riscv_xlen == 64 51 | if(timer == 0) 52 | irq_no = 10; 53 | else if(timer == 1) 54 | irq_no = 11; 55 | else if(timer == 2) 56 | irq_no = 12; 57 | 58 | #else 59 | if(timer == 0) 60 | irq_no = 7; 61 | else if(timer == 1) 62 | irq_no = 8; 63 | else if(timer == 2) 64 | irq_no = 9; 65 | #endif 66 | interrupt_enable(irq_no); 67 | irq_register_handler(irq_no, handler); 68 | 69 | __asm__ __volatile__ ("fence"); 70 | 71 | TIMER(timer).control = 0x0; // Disable timer. 72 | TIMER(timer).load_count = clocks; // Load timer with no of clocks. 73 | TIMER(timer).control = 0x3; // Enable timer with intr unmasked. (0011) 74 | 75 | __asm__ __volatile__ ("fence"); 76 | } 77 | 78 | 79 | /** @fn void TIMER_enable(unsigned char timer) 80 | @brief Enable timer with interrupt 81 | @details The selected timer and its interrupt is enabled and unmasked. 82 | 83 | @param[in] unsigned char timer_no: Selected timer. 84 | @param[Out] No output parameter. 85 | */ 86 | void TIMER_enable(unsigned char timer) { 87 | 88 | TIMER(timer).control = 0x3; // Enable timer with intr unmasked. 89 | __asm__ __volatile__ ("fence"); 90 | } 91 | 92 | 93 | /** @fn void TIMER_disable(unsigned char timer) 94 | @brief Disable timer 95 | @details The selected timer and its interrupt is disabled. 96 | 97 | @param[in] unsigned char timer_no: Selected timer. 98 | @param[Out] No output parameter. 99 | */ 100 | void TIMER_disable(unsigned char timer) { 101 | 102 | TIMER(timer).control = 0x0; // Disable timer. 103 | __asm__ __volatile__ ("fence"); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | SPDX-License-Identifier: MIT 3 | Project CMakeLists.txt 4 | Author : Debayan Sutradhar (@rnayabed) 5 | ]] 6 | 7 | 8 | cmake_minimum_required(VERSION 3.16) 9 | 10 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/taurusToolchain.cmake) 11 | 12 | set(VERSION 0.1) 13 | 14 | project(taurus 15 | VERSION ${VERSION} 16 | LANGUAGES C ASM 17 | DESCRIPTION "SDK For CDAC Vega Processors") 18 | 19 | set(HEADERS 20 | include/gpio.h 21 | include/i2c.h 22 | include/qspi.h 23 | include/m25p80_eeprom.h 24 | include/config.h 25 | include/spi.h 26 | include/timer.h 27 | include/uart.h 28 | include/debug_uart.h 29 | include/adc.h 30 | include/interrupt.h 31 | include/pwmc.h 32 | include/encoding.h 33 | include/stdlib.h) 34 | 35 | add_library(taurus STATIC 36 | common/crt.S 37 | common/rawfloat.c 38 | common/stdlib.c 39 | 40 | ${HEADERS} 41 | 42 | drivers/uart.c 43 | drivers/debug_uart.c 44 | drivers/gpio.c 45 | drivers/i2c.c 46 | drivers/qspi.c 47 | drivers/spi.c 48 | drivers/timer.c 49 | drivers/interrupt.c 50 | drivers/pwmc.c) 51 | 52 | set_target_properties(taurus PROPERTIES 53 | PUBLIC_HEADER "${HEADERS}" 54 | C_STANDARD 17 55 | C_EXTENSIONS ON) 56 | 57 | target_include_directories(taurus PUBLIC 58 | $ 59 | $) 60 | 61 | if (NOT CMAKE_BUILD_TYPE) 62 | set(CMAKE_BUILD_TYPE Debug CACHE STRING) 63 | message(WARNING "CMAKE_BUILD_TYPE not specified. Defaulting to '${CMAKE_BUILD_TYPE}'") 64 | endif() 65 | 66 | # -Wall -Wextra -Werror -Wpedantic 67 | 68 | target_compile_options(taurus PUBLIC 69 | -T${CMAKE_SOURCE_DIR}/common/mbl.lds 70 | 71 | -march=${RISCV_ARCH} -mabi=${RISCV_ABI} -mcmodel=${RISCV_CMODEL} 72 | 73 | --specs=nosys.specs --specs=nano.specs 74 | 75 | $<$:-Og -ggdb3> 76 | $<$:-O3> 77 | $<$:-Os> 78 | $<$:-O3 -ggdb3> 79 | ) 80 | 81 | target_link_options(taurus PUBLIC 82 | -T${CMAKE_SOURCE_DIR}/common/mbl.lds 83 | 84 | --specs=nosys.specs --specs=nano.specs 85 | 86 | -march=${RISCV_ARCH} -mabi=${RISCV_ABI} -mcmodel=${RISCV_CMODEL} 87 | 88 | -Wl,--gc-sections -Wl,-Map=taurus.map 89 | 90 | -nostartfiles -fno-builtin-printf -fno-builtin-puts 91 | -fdata-sections -ffunction-sections -fno-builtin-memcmp 92 | 93 | $<$,$,$>:-s>) 94 | 95 | install(TARGETS taurus 96 | EXPORT taurus-export 97 | PUBLIC_HEADER DESTINATION include/taurus 98 | ARCHIVE DESTINATION lib) 99 | 100 | install(EXPORT taurus-export 101 | FILE taurusTargets.cmake 102 | NAMESPACE taurus:: 103 | DESTINATION lib/cmake/taurus) 104 | 105 | include(CMakePackageConfigHelpers) 106 | 107 | write_basic_package_version_file( 108 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/taurusConfigVersion.cmake 109 | VERSION ${VERSION} 110 | COMPATIBILITY SameMajorVersion) 111 | 112 | configure_file( 113 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/taurusConfig.cmake.in 114 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/taurusConfig.cmake 115 | @ONLY) 116 | 117 | install(FILES 118 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/taurusConfig.cmake 119 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/taurusConfigVersion.cmake 120 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/taurusToolchain.cmake 121 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/taurusUploader.cmake.in 122 | DESTINATION lib/cmake/taurus) 123 | 124 | if(CMAKE_HOST_UNIX) 125 | add_custom_target(uninstall COMMAND 126 | xargs rm -rfv < install_manifest.txt && 127 | rm -rfv ${CMAKE_INSTALL_PREFIX}/lib/cmake/taurus && 128 | rm -rfv ${CMAKE_INSTALL_PREFIX}/include/taurus) 129 | endif() 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Taurus 2 | 3 | ![version](https://img.shields.io/badge/Version-0.1-green) 4 | 5 | This is a fork of [CDAC Vega](https://vegaprocessors.in/devboards) SDK with additional improvements. 6 | It is an experiment and mostly for learning how such systems work, for now. 7 | 8 | Contributions are welcome :) 9 | 10 | ## [Getting Started](https://github.com/rnayabed/taurus/blob/master/docs/getting-started.md) 11 | 12 | ## Supported Platforms 13 | 14 | - Linux 15 | - Windows 16 | 17 | ## Prerequisites 18 | 19 | - CMake 20 | - Ninja (Only on Windows) 21 | - RISC-V GNU Compiler Toolchain 22 | 23 | ## Comparison with official SDK 24 | 25 | - Usage of CMake instead of GNU Make: This allows usage of multiple build systems and compilation on Windows and MacOS alongside Linux. 26 | - Integration with [vegadude](https://github.com/rnayabed/vegadude) uploader tool for seamless development experience. 27 | - Cleaner code 28 | - Examples moved to seperate [repository](https://github.com/rnayabed/taurus-examples). 29 | - setup.sh: Completely rewritten with fine tunable features. See setup script usage for more information. 30 | - gpio: 31 | - All GPIO pins are intialised as OUTPUT LOW. 32 | Note: On Aries v2.0, Pin 26,27,29 and 30 are set to OUTPUT HIGH as these are inbuilt active-low LEDs. 33 | - Removed led: Not needed as it is the same as gpio. 34 | - config.h 35 | - Refactor, added SFRs 36 | - timer 37 | - Rewritten and simplified methods 38 | 39 | ## TODO 40 | 41 | - Avoid GNU extensions to allow usage of RISC-V LLVM toolchain 42 | - Documentation 43 | 44 | ## Setup script usage 45 | 46 | ``` 47 | Usage: [-tb | --target-board] [-ts | --target-soc] 48 | [-tt | --toolchain-triplet] [-tp | --toolchain-path] 49 | [-ip | --install-path] [-vp | --vegadude-path] 50 | [-nm | --no-minicom] 51 | [-h | --help] 52 | 53 | Option Summary: 54 | -tb | --target-board Required if --target-soc not provided. 55 | Set the target development board to 56 | build Taurus for. Adds extra optimisations 57 | for board if available. 58 | Valid targets are: 59 | ARIES_V2 ARIES_V3 ARIES_MICRO_V1 ARIES_IOT_V1 60 | 61 | -ts | --target-soc Required if --target-board not provided. 62 | Set the target System-on-Chip to build 63 | Taurus for. 64 | Valid targets are: 65 | THEJAS32 THEJAS64 CDACFPGA 66 | 67 | -tt | --toolchain-triplet Required. RISC-V GNU Compiler Toolchain 68 | triplet. 69 | Example: 'riscv64-unknown-elf' 70 | 71 | -tp | --toolchain-path Optional. Specify the absolute path of 72 | toolchain if it is not present in PATH. 73 | 74 | -ip | --install-path Optional. Path where Taurus will be 75 | installed. 76 | 77 | -vp | --vegadude-path Optional. Provide vegadude path for taurus integration. 78 | Not required if vegadude is already present in PATH. 79 | 80 | -nm | --no-minicom Optional. Do not create minicom 81 | configuration file. Configuration is 82 | created if not specified. 83 | 84 | -h --help Print this message. 85 | ``` 86 | 87 | Auto-minicom configuration is created only in Linux. 88 | 89 | ## Credits 90 | 91 | Originally developed by [Centre for Development of Advanced Computing, India](https://www.cdac.in/). 92 | 93 | Forked and further developed by [Debayan Sutradhar](https://github.com/rnayabed) & 94 | [Avra Mitra](https://github.com/abhra0897). All Rights Reserved. 95 | 96 | ## License 97 | 98 | Taurus is licensed under the [MIT License](https://github.com/rnayabed/taurus/blob/master/LICENSE). 99 | -------------------------------------------------------------------------------- /docs/create-a-project.md: -------------------------------------------------------------------------------- 1 | # Create a project 2 | 3 | Taurus uses CMake. 4 | 5 | Let's create a simple blink project. 6 | 7 | Our project will have the following directory tree 8 | ``` 9 | . 10 | ├── CMakeLists.txt 11 | └── led_toggle.c 12 | ``` 13 | 14 | ## 15 | 16 | ### CMakeLists.txt 17 | 18 | ```cmake 19 | cmake_minimum_required(VERSION 3.16) 20 | 21 | find_package(taurus 0.1 REQUIRED) 22 | 23 | project(led_toggle 24 | LANGUAGES C) 25 | 26 | add_executable(${PROJECT_NAME} 27 | led_toggle.c) 28 | 29 | target_link_libraries(${PROJECT_NAME} 30 | PRIVATE taurus::taurus) 31 | 32 | configure_taurus_uploader( 33 | START_AFTER_UPLOAD 34 | TARGET_PATH /dev/ttyUSB0) 35 | ``` 36 | 37 | 38 | The `configure_taurus_uploader` is a custom function provided by the Taurus SDK. 39 | It integrates your project with [vegadude](https://github.com/rnayabed/vegadude.git) so that you can easily upload programs 40 | directly from CMake. 41 | 42 | `configure_taurus_uploader` as additional options: 43 | 44 | ``` 45 | configure_taurus_uploader( 46 | [START_AFTER_UPLOAD - flag if you immediately want to start program after upload] 47 | EXEC_NAME 48 | TARGET_PATH 49 | VEGADUDE_ARGS 50 | ``` 51 | 52 | For detailed usage of vegadude, check it's [usage](https://github.com/rnayabed/vegadude#usage). 53 | 54 | ### led_toggle.c 55 | 56 | ```cpp 57 | #include 58 | #include 59 | #include 60 | 61 | int current_status = LOW; 62 | 63 | void timer0_interrupt_handler() 64 | { 65 | TIMER_acknowledge_interrupt(TIMER_0); 66 | 67 | if (current_status == LOW) 68 | { 69 | printf("LED ON\n"); 70 | current_status = HIGH; 71 | } 72 | else 73 | { 74 | printf("LED OFF\n"); 75 | current_status = LOW; 76 | } 77 | 78 | GPIO_write_pin(GPIO_25, current_status); 79 | } 80 | 81 | void main() 82 | { 83 | TIMER_setup_interrupt_seconds(TIMER_0, 1, timer0_interrupt_handler); 84 | } 85 | ``` 86 | 87 | We use hardware timers with interrupts to blink an LED. 88 | You could use busy looping using `TIMER_setup_delay_seconds(unsigned char timer, unsigned long seconds)` as well. 89 | 90 | ## Build and Run 91 | 92 | Just like any usual CMake project, just run: 93 | 94 | ### Linux: 95 | ``` 96 | cmake -B build 97 | ``` 98 | 99 | **If you have installed Taurus in a custom location, you need to add it to PATH, or use `-DCMAKE_PREFIX_PATH=` as well.** 100 | 101 | 102 | ### Windows: 103 | ``` 104 | cmake -B build -G Ninja 105 | ``` 106 | 107 | **You need to add the installed location of Taurus SDK (by default `C:/Program Files (x86)/taurus`) to PATH, or use `-DCMAKE_PREFIX_PATH=` as well.** 108 | 109 | 110 | To build, run: 111 | 112 | ``` 113 | cmake --build build 114 | ``` 115 | 116 | To upload the program on your Aries board, run: 117 | 118 | ``` 119 | cmake --install build 120 | ``` 121 | 122 | You will then get an output like this: 123 | 124 | ``` 125 | $> cmake --install build 126 | -- Install configuration: "" 127 | vegadude 1.0 128 | 129 | 130 | ================================================ 131 | Device Path: "/dev/ttyUSB0" 132 | Binary Path: "/home/rnayabed/code/rnayabed/taurus-examples/gpio/led_toggle/build/led_toggle" 133 | Target device properties: 134 | Parity: 0 135 | Stop bits: 1 136 | RTS CTS: 0 137 | Bits: 8 138 | Baud rate: 115200 139 | Read Timeout (in milliseconds): 500 140 | XMODEM Block Size 128 141 | XMODEM Max Retry: 10 142 | ================================================ 143 | 144 | Progress [##################################################] - 100% - Sent block 213/213 145 | Successfully uploaded and started program! 146 | ``` 147 | 148 | If you have an LED connected to GPIO 25, it will blink with a duration of 1 second. 149 | 150 | If you use Linux, Taurus creates a minicom configuration by default unless `--no-minicom` is used during it's setup. 151 | 152 | If you have minicom installed, you can run `sudo minicom aries` and the output would something like this: 153 | ``` 154 | LED ON 155 | LED OFF 156 | LED ON 157 | LED OFF 158 | LED ON 159 | LED OFF 160 | LED ON 161 | LED OFF 162 | LED ON 163 | LED OFF 164 | ... 165 | ``` 166 | 167 | If you are on Windows, you can use any terminal with serial support. 168 | -------------------------------------------------------------------------------- /include/adxl345.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADXL345_H 2 | #define _ADXL345_H 3 | /** 4 | @file adxl345.h 5 | @brief header file for ADXL345 sensor 6 | @detail 7 | */ 8 | /*************************************************** 9 | * Module name: ADXL345.h 10 | * 11 | * Copyright 2020 Company CDAC(T). 12 | * All Rights Reserved. 13 | * 14 | * The information contained herein is confidential 15 | * property of Company. The user, copying, transfer or 16 | * disclosure of such information is prohibited except 17 | * by express written agreement with Company. 18 | * 19 | * 20 | * Module Description: 21 | * ADXL345 registers and function declarations 22 | * 23 | ***************************************************/ 24 | /*========================================================================= 25 | I2C ADDRESS/BITS 26 | -----------------------------------------------------------------------*/ 27 | #define ADXL345_I2C_ADDR_WR (0xA6) ///< Assumes ALT address pin low 28 | #define ADXL345_I2C_ADDR_RD (0xA7) ///< Assumes ALT address pin low 29 | /*=========================================================================*/ 30 | 31 | /*========================================================================= 32 | REGISTERS 33 | -----------------------------------------------------------------------*/ 34 | #define ADXL345_REG_DEVID (0x00) ///< Device ID 35 | #define ADXL345_REG_THRESH_TAP (0x1D) ///< Tap threshold 36 | #define ADXL345_REG_OFSX (0x1E) ///< X-axis offset 37 | #define ADXL345_REG_OFSY (0x1F) ///< Y-axis offset 38 | #define ADXL345_REG_OFSZ (0x20) ///< Z-axis offset 39 | #define ADXL345_REG_DUR (0x21) ///< Tap duration 40 | #define ADXL345_REG_LATENT (0x22) ///< Tap latency 41 | #define ADXL345_REG_WINDOW (0x23) ///< Tap window 42 | #define ADXL345_REG_THRESH_ACT (0x24) ///< Activity threshold 43 | #define ADXL345_REG_THRESH_INACT (0x25) ///< Inactivity threshold 44 | #define ADXL345_REG_TIME_INACT (0x26) ///< Inactivity time 45 | #define ADXL345_REG_ACT_INACT_CTL \ 46 | (0x27) ///< Axis enable control for activity and inactivity detection 47 | #define ADXL345_REG_THRESH_FF (0x28) ///< Free-fall threshold 48 | #define ADXL345_REG_TIME_FF (0x29) ///< Free-fall time 49 | #define ADXL345_REG_TAP_AXES (0x2A) ///< Axis control for single/double tap 50 | #define ADXL345_REG_ACT_TAP_STATUS (0x2B) ///< Source for single/double tap 51 | #define ADXL345_REG_BW_RATE (0x2C) ///< Data rate and power mode control 52 | #define ADXL345_REG_POWER_CTL (0x2D) ///< Power-saving features control 53 | #define ADXL345_REG_INT_ENABLE (0x2E) ///< Interrupt enable control 54 | #define ADXL345_REG_INT_MAP (0x2F) ///< Interrupt mapping control 55 | #define ADXL345_REG_INT_SOURCE (0x30) ///< Source of interrupts 56 | #define ADXL345_REG_DATA_FORMAT (0x31) ///< Data format control 57 | #define ADXL345_REG_DATAX0 (0x32) ///< X-axis data 0 58 | #define ADXL345_REG_DATAX1 (0x33) ///< X-axis data 1 59 | #define ADXL345_REG_DATAY0 (0x34) ///< Y-axis data 0 60 | #define ADXL345_REG_DATAY1 (0x35) ///< Y-axis data 1 61 | #define ADXL345_REG_DATAZ0 (0x36) ///< Z-axis data 0 62 | #define ADXL345_REG_DATAZ1 (0x37) ///< Z-axis data 1 63 | #define ADXL345_REG_FIFO_CTL (0x38) ///< FIFO control 64 | #define ADXL345_REG_FIFO_STATUS (0x39) ///< FIFO status 65 | /*=========================================================================*/ 66 | 67 | /* Constants 68 | 69 | ***************************************************/ 70 | #define ADXL345_MG2G_MULTIPLIER (0.004) ///< 4mg per lsb 71 | #define SENSORS_GRAVITY_STANDARD (9.80665F) /**< Earth's gravity in m/s^2 */ 72 | 73 | 74 | /** 75 | * @brief Used with register 0x31 (ADXL345_REG_DATA_FORMAT) to set g range 76 | * 77 | */ 78 | typedef enum { 79 | ADXL345_RANGE_16_G = 0b11, ///< +/- 16g 80 | ADXL345_RANGE_8_G = 0b10, ///< +/- 8g 81 | ADXL345_RANGE_4_G = 0b01, ///< +/- 4g 82 | ADXL345_RANGE_2_G = 0b00 ///< +/- 2g (default value) 83 | } range_t; 84 | 85 | /* Define section 86 | * 87 | * 88 | ***************************************************/ 89 | 90 | 91 | 92 | 93 | 94 | 95 | /***************************************************/ 96 | 97 | 98 | /* Function declaration section 99 | * 100 | * 101 | ***************************************************/ 102 | US i2c_ADXL345_get_acc(UC i2c_num, UC Slave_Address_Wr, 103 | UC Slave_Address_Rd, UC Adxl_Address); 104 | void i2c_ADXL345_set_range(UC i2c_num, UC Slave_Address_Wr,range_t range,UC Adxl_Address); 105 | void i2c_ADXL345_write_register(UC i2c_num, UC Slave_Address_Wr,UC Adxl_Address,UC value); 106 | UC i2c_ADXL345_read_register(UC i2c_num, UC Slave_Address_Wr,UC Slave_Address_Rd,UC Adxl_Address); 107 | 108 | #endif /* _ADXL345_H */ 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /include/spi.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPI_H 2 | #define _SPI_H 3 | /** 4 | @file spi.h 5 | @brief header file for SPI driver 6 | @detail 7 | */ 8 | /*************************************************** 9 | * Module name: spi.h 10 | * 11 | * Copyright 2020 Company CDAC(T). 12 | * All Rights Reserved. 13 | * 14 | * The information contained herein is confidential 15 | * property of Company. The user, copying, transfer or 16 | * disclosure of such information is prohibited except 17 | * by express written agreement with Company. 18 | * 19 | * 20 | * Module Description: 21 | * SPI registers and function declarations 22 | * 23 | ***************************************************/ 24 | 25 | /* Include section 26 | * 27 | ***************************************************/ 28 | #include "config.h" 29 | /* Define section 30 | * 31 | * 32 | ***************************************************/ 33 | #define MDP_SPI_0 0 34 | #define MDP_SPI_1 1 35 | #define MDP_SPI_2 2 36 | #define MDP_SPI_3 3 37 | 38 | #define SPI_INTR_MODE 1 39 | #define SPI_POLLING_MODE 2 40 | #define DATA_BYTES 65536 41 | 42 | // SPI BASE ADDRESS 43 | 44 | #define LOW 0 45 | #define HIGH 1 46 | 47 | #define MSB 0 48 | #define LSB 1 49 | 50 | #define SPI_FIXD_PERIPH 0 51 | #define SPI_VAR_PERIPH 1 52 | 53 | #define CPOL_MODE_0 0 54 | #define CPHA_MODE_0 0 55 | #define CPOL_MODE_3 1 56 | #define CPHA_MODE_3 1 57 | 58 | #define BPT_8 0 59 | 60 | #define TXINTR_DIS 0 61 | #define RXINTR_DIS 0 62 | 63 | #define TXINTR_EN 1 64 | #define RXINTR_EN 1 65 | 66 | #define SPI_MODE_0 0 67 | #define SPI_MODE_3 3 68 | 69 | #define SPI_CS_0 0 70 | #define SPI_CS_1 1 71 | #define SPI_CS_2 2 72 | #define SPI_CS_3 3 73 | 74 | #define RX_TX_INTR_DIS 0 75 | #define TX_DIS_RX_EN_INTR 1 76 | #define RX_DIS_TX_EN_INTR 2 77 | #define RX_TX_INTR_EN 3 78 | 79 | #define SPI_BAUD_CFD_4 0 80 | #define SPI_BAUD_CFD_8 1 81 | #define SPI_BAUD_CFD_16 2 82 | #define SPI_BAUD_CFD_32 3 83 | #define SPI_BAUD_CFD_64 4 84 | #define SPI_BAUD_CFD_128 5 85 | #define SPI_BAUD_CFD_256 6 86 | #define SPI_BAUD_CFD_512 7 87 | #define SPI_BAUD_CFD_1024 8 88 | #define SPI_BAUD_CFD_2048 9 89 | 90 | #define SPI_BUSY_BIT (1<<4) 91 | #define SPI_OVERR_BIT (1<<5) 92 | #define SPI_RX_COMPLETE_BIT (1<<6) 93 | #define SPI_TX_HOLD_EMPTY_BIT (1<<7) 94 | 95 | #define SPI_RX_INT_STATUS_BIT (1<<2) 96 | #define SPI_TX_INT_STATUS_BIT (1<<3) 97 | 98 | #define SPI_RX_INTR 1 99 | #define SPI_TX_INTR 2 100 | 101 | /*************Micron M25P80 Serial Flash************* 102 | *************Embedded Memory Command Set************/ 103 | /*#define WR_DISABLE_LATCH_SPI_CMD 0x04 104 | #define WR_EN_LATCH_SPI_CMD 0x06 105 | #define BYTE_PAGE_PGM_SPI_CMD 0x02 106 | #define RD_DATA_BYTES_SPI_CMD 0x03 107 | #define RD_STATUS_REG_SPI_CMD 0x05 108 | #define RDID_SPI_CMD 0x83 109 | /***************************************************/ 110 | 111 | typedef struct { 112 | 113 | union { 114 | struct { 115 | US PeriphCS :2, Periph :1, DataOrder :1, Mode :2, SPIrxTxIntr :2, 116 | CSAAT :1, Dbits :4, Reserved :3; 117 | }__attribute__((packed)) Bits; 118 | US hword; 119 | } Control; //0x00 120 | UI Status; //0x04 121 | UI Baudrate; //0x08 122 | UI TxData; //0x0c 123 | UI RxData; //0x10 124 | } SPIregType; 125 | 126 | typedef union { 127 | struct { 128 | US PeriphChipSelect :2, PeriphType :1, DataOrder :1, Mode :2, SPIrxTxIntr :2, 129 | CSAAT :1, Dbits :4, Reserved :3; 130 | } Bits; 131 | US Value; 132 | } SPIcntrlRegType; 133 | 134 | //Register address mapping 135 | #define SPIreg(i) (*((volatile SPIregType *)(SPI_BASE_ADDR(i) + (0x100 * (i % 2))))) 136 | #define SPI_VARIABLE_PERIPHERAL 1 137 | #define SPI_FIXED_PERIPHERAL 0 138 | #define SPI_MSB_FIRST 0 139 | #define SPI_LSB_FIRST 1 140 | 141 | /* Function declaration section 142 | * 143 | * 144 | ***************************************************/ 145 | 146 | void SPI_init(UC spi_number); 147 | void SPI_config(UC spi_number, SPIcntrlRegType spi_control_reg); 148 | void SPI_set_baud(UC spi_number, UC bBaudCFD); 149 | UI SPI_get_slave_select(UC spi_number); 150 | void SPI_set_slave_select(UC spi_number, UI slave_sel_val); 151 | UC SPI_check_overrun(UC spi_number); 152 | void SPI_set_intr(UC spi_number, UC tx_intr, UC rx_intr); 153 | US SPI_receive(UC spi_number); 154 | void SPI_transmit(UC spi_number, US bData); 155 | void SPI_intr_handler(UC spi_number); 156 | void SPI_wait_if_busy(UC spi_number); 157 | void SPI_set_CSAAT_pin(UC spi_number, UC status); 158 | US SPI_read_rx_reg(UC spi_number); 159 | void SPI_write_tx_reg(UC spi_number, US bData); 160 | UC spi_intr_status(UC spi_number); 161 | void spi_register_isr(UC spi_number, void (*spi_isr)()); 162 | 163 | //void (*spi_handle_rx_intr)(void); 164 | //void (*spi_handle_tx_intr)(void); 165 | 166 | #endif /* _SPI_H */ 167 | 168 | -------------------------------------------------------------------------------- /drivers/debug_uart.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file debug_uart.c 3 | @brief Contains routines for basic uart for debugging/Printf 4 | @detail Includes software functions to initialize, 5 | configure, transmit and receive over UART 6 | */ 7 | 8 | #include 9 | 10 | /** 11 | @fn init_uart 12 | @brief default baud rate and frame initialization 13 | @details To initialize UART: Baud Rate = 115200 Clock 25MHz 14 | Calculate Divisor(Divisor = Input frequency / (Baud rate X 16) ) 15 | for the baud rate and configure uart register. UART frame is initialized by 16 | setting the data bits,parity bits and stop bits 17 | 8 Data bits, 1 Stop bit, no Parity, Disable DR interrupt & THRE interrupt 18 | @param[Out] No ouput parameter. 19 | @return Void function. 20 | */ 21 | void init_uart(void) { 22 | uart_regs.UART_LCR = 0x83; //Divisor latch enabled 23 | uart_regs.UART_DR = 0x15; //0x0b-20mHz,0x02-5mHz,0x10-30mHz; 24 | //0x0e-25mHz;0x0f-29mHz,0x1b-50mHz; 0x15-40mHz ;0x28-75mHz //Divisor LSB 25 | uart_regs.UART_IE = 0x00; //Divisor MSB 26 | uart_regs.UART_LCR = 0x03; //Divisor latch disabled, stop-bits = 1, parity = none, data-bits = 8 27 | uart_regs.UART_IE = 0x00; //Interrupts disabled 28 | __asm__ __volatile__ ("fence"); 29 | } 30 | 31 | 32 | /** 33 | @fn void void tx_uart(UC tx_char) 34 | @brief 1 byte character transmission 35 | @details Transmit 1 character through uart.Proceeds only when transmitter is idle 36 | @param[in] unsigned char(bTxCharacter--character to be transmitted) 37 | @return Void function. 38 | */ 39 | void tx_uart(UC tx_char) { 40 | UC lsr; 41 | 42 | uart_regs.UART_DR = tx_char; 43 | __asm__ __volatile__ ("fence"); 44 | do { 45 | lsr = uart_regs.UART_LSR; 46 | __asm__ __volatile__ ("fence"); 47 | lsr = lsr & 0x20; 48 | } while (lsr != 0x20); 49 | } 50 | 51 | 52 | /** 53 | @fn UC rx_uart(void) 54 | @brief 1 byte character reception 55 | @details Receives 1 character thcrough uart 56 | @return unsigned char Rxd_data--data received 57 | */ 58 | UC rx_uart(void) { 59 | UC lsr, Rx_char; 60 | 61 | do { 62 | lsr = uart_regs.UART_LSR; 63 | __asm__ __volatile__ ("fence"); 64 | } while ((lsr & 1) == 0); 65 | 66 | Rx_char = uart_regs.UART_DR; 67 | __asm__ __volatile__ ("fence"); 68 | 69 | //uart_regs.UART_LSR &= ~0x1; //For emulation only FIXME 70 | return Rx_char; 71 | } 72 | 73 | 74 | /** 75 | @fn UL get_decimal(UC noOfDigits) 76 | @brief get decimal value of entered ascii digits 77 | @details Receives number of digits to read 78 | @return unsigned long Returns the decimal value 79 | */ 80 | UL get_decimal(UC noOfDigits) { 81 | UC i, rx = 0, ascii[16]; 82 | 83 | UL number = 0, cnt = 0, temp = 1; 84 | 85 | for (i = 1; i < noOfDigits; i++) 86 | temp *= 10; 87 | 88 | i = 0; 89 | while (1) { 90 | 91 | if (i < noOfDigits) { 92 | while (1) { 93 | rx = rx_uart(); 94 | if (rx >= '0' && rx <= '9') { 95 | tx_uart(rx); 96 | ascii[i] = rx; 97 | break; 98 | } 99 | if (rx == '\b') { 100 | if (i > 0) { 101 | tx_uart(rx); 102 | tx_uart(' '); 103 | tx_uart(rx); 104 | i--; 105 | } 106 | continue; 107 | } 108 | 109 | } 110 | i++; 111 | 112 | } else if (i == noOfDigits) { 113 | rx = rx_uart(); 114 | if (rx == '\r') { 115 | break; 116 | } else if (rx == '\b') { 117 | tx_uart(rx); 118 | tx_uart(' '); 119 | tx_uart(rx); 120 | i--; 121 | continue; 122 | } 123 | } 124 | } 125 | for (i = 0; i < noOfDigits; i++) { 126 | ascii[i] -= '0'; //ascii 127 | number = number + (temp * ascii[i]); 128 | temp = temp / 10; 129 | } 130 | return number; 131 | } 132 | 133 | 134 | /** 135 | @fn UL get_long_int(UC noofBytes) 136 | @brief get long integer value of entered ascii digits 137 | @details Receives number of digits to read 138 | @return unsigned long Returns the long integer value 139 | */ 140 | UL get_long_int(UC noofBytes) { 141 | UC i, rx = 0, temp[16]; 142 | UI hex_val = 0; 143 | i = 0; 144 | while (1) { 145 | if (i < noofBytes) { 146 | /*if ((noofBytes == 4) || (noofBytes == 2)) { 147 | if (i > 0) 148 | Tx_uart('-'); 149 | }*/ 150 | rx = get_hex(); 151 | if (rx == '\b') { 152 | if (i > 0) { 153 | tx_uart(rx); 154 | tx_uart(' '); 155 | tx_uart(rx); 156 | tx_uart(rx); 157 | tx_uart(' '); 158 | tx_uart(rx); 159 | i--; 160 | } 161 | continue; 162 | } 163 | //temp <<= 8; 164 | //temp = temp + rx; 165 | temp[i] = rx; 166 | 167 | i++; 168 | } else if (i == noofBytes) { 169 | rx = rx_uart(); 170 | if (rx == '\r') { 171 | break; 172 | } else if (rx == '\b') { 173 | tx_uart(rx); 174 | tx_uart(' '); 175 | tx_uart(rx); 176 | tx_uart(rx); 177 | tx_uart(' '); 178 | tx_uart(rx); 179 | i--; 180 | continue; 181 | } 182 | } 183 | } 184 | 185 | for (i = 0; i < noofBytes; i++) { 186 | hex_val <<= 8; 187 | hex_val |= temp[i]; 188 | } 189 | 190 | return hex_val; 191 | } 192 | 193 | 194 | /** 195 | @fn UC get_hex() 196 | @brief get hexadecimal value of entered digits 197 | @details Receives number of digits to read 198 | @return unsigned long Returns the hexadecimal value 199 | */ 200 | UC get_hex() { 201 | unsigned char number = 0, dig1, dig2, count = 2, rx; 202 | while (count) { 203 | rx = rx_uart(); 204 | if (rx == '\b') { 205 | if (count < 2) { 206 | tx_uart(rx); 207 | tx_uart(' '); 208 | tx_uart(rx); 209 | count++; 210 | continue; 211 | } else 212 | return rx; 213 | } 214 | 215 | if ((rx >= 0x30) && (rx <= 0x39)) { 216 | tx_uart(rx); 217 | rx = rx - 0x30; 218 | } else if ((rx >= 'A') && (rx <= 'F')) { 219 | tx_uart(rx); 220 | rx = rx - 0x37; 221 | } else if ((rx >= 'a') && (rx <= 'f')) { 222 | tx_uart(rx); 223 | rx = rx - 0x57; 224 | } 225 | 226 | else 227 | continue; 228 | if (count == 2) 229 | dig1 = rx; 230 | else 231 | dig2 = rx; 232 | count--; 233 | } 234 | number = (dig1 << 4); 235 | number |= dig2; 236 | return number; 237 | } 238 | 239 | -------------------------------------------------------------------------------- /include/qspi.h: -------------------------------------------------------------------------------- 1 | #ifndef _QSPI_H 2 | #define _QSPI_H 3 | /** 4 | @file qspi.h 5 | @brief header file for QSPI Flash driver 6 | @detail 7 | */ 8 | /*************************************************** 9 | * Module name: qspi.h 10 | * 11 | * Copyright 2020 Company CDAC(T). 12 | * All Rights Reserved. 13 | * 14 | * The information contained herein is confidential 15 | * property of Company. The user, copying, transfer or 16 | * disclosure of such information is prohibited except 17 | * by express written agreement with Company. 18 | * 19 | * 20 | * Module Description: 21 | * QSPI registers and function declarations 22 | * 23 | ***************************************************/ 24 | 25 | /* Include section 26 | * 27 | ***************************************************/ 28 | 29 | /* Define section 30 | * 31 | * 32 | ***************************************************/ 33 | #if __riscv_xlen == 64 //QSPI driver available only for thejas64 34 | #define QSPI_0 0 35 | #define QSPI_1 1 36 | #define QSPI_2 2 37 | #define QSPI_3 3 38 | 39 | 40 | #define PRESCALAR_MAX 00 41 | #define PRESCALAR_MIN 0xFF 42 | 43 | #define CK_MODE_0 0 44 | #define CK_MODE_1 1 45 | 46 | #define CHIP_HIGH_TIME 0x05 47 | 48 | #define INSTR_LINE_1 0x01 49 | 50 | #define INSTR_LINE_3 0x03 51 | 52 | 53 | #define POLLING_INTERVAL_256 0x40 54 | #define AUTO_POLL_STOP_ON 0x01 55 | #define AUTO_POLL_STOP_OFF 0x00 56 | #define POLL_MODE_AND 0X00 57 | #define POLL_MODE_OR 0X01 58 | 59 | 60 | #define DATA_LINE_1 0x01 61 | 62 | #define DATA_LINE_3 0x03 63 | 64 | #define ADDR_LINE_1 0x01 65 | 66 | #define ADDR_LINE_3 0x03 67 | 68 | #define DATA_SIZE_0 0x00 69 | #define DATA_SIZE_1 0x01 70 | #define DATA_SIZE_2 0x02 71 | #define DATA_SIZE_3 0x03 72 | 73 | #define ADDR_SIZE_0 0x00 74 | #define ADDR_SIZE_1 0x01 75 | #define ADDR_SIZE_2 0x02 76 | #define ADDR_SIZE_3 0x03 77 | 78 | 79 | #define INDIRECT_WR 0x00 80 | #define INDIRECT_RD 0x01 81 | #define AUTOPOLL_RD 0X02 82 | 83 | 84 | 85 | 86 | 87 | 88 | #define QSPI_BASE_ADDR 0x10200100UL 89 | 90 | /*************Micron M25P80 Serial Flash************* 91 | *************Embedded Memory Command Set************/ 92 | #define RD_STATUS1_REG_QSPI_CMD 0x05 93 | #define RD_FLASH_ID_CMD 0x9F 94 | #define RESET_ENABLE_CMD 0x66 95 | #define RESET_FLASH_CMD 0x99 96 | #define WR_EN_LATCH_FLASH_CMD 0x06 97 | #define BYTE4_ADDRESS_ENABLE_CMD 0xB7 98 | #define QPI_MODE_ENABLE_CMD 0x35 99 | #define SECTOR_ERASE_4BYTE_CMD 0x21 100 | #define RD_XTD_RDREG_CMD 0x81 101 | #define CLR_XTD_RDREG_CMD 0x82 102 | #define PAGE_PROGRAM_4PP_CMD 0x12 103 | #define FAST_READ_4FRD_CMD 0x0C 104 | /*#define WR_DISABLE_LATCH_SPI_CMD 0x04 105 | 106 | #define BYTE_PAGE_PGM_SPI_CMD 0x02 107 | #define RD_DATA_BYTES_SPI_CMD 0x03 108 | #define RD_STATUS_REG_SPI_CMD 0x05 109 | #define RDID_SPI_CMD 0x83 110 | /***************************************************/ 111 | 112 | 113 | 114 | #define FLASH_MEMORY_SIZE 0X19 115 | typedef unsigned char UC; //1 Byte 116 | typedef unsigned short US; //2 Bytes 117 | typedef unsigned int UI; //4 Bytes 118 | typedef unsigned long UL; //8 Bytes 119 | 120 | typedef struct { 121 | UL QSPI_CSR; 122 | UL QSPI_DCR; 123 | UL QSPI_ADLR; 124 | UL QSPI_CCR; 125 | UL QSPI_DR; 126 | UL QSPI_SPR; 127 | UL QSPI_FCR; 128 | UL QSPI_DSR; 129 | 130 | } QSPI_REG_TYPE; 131 | #define QSPI_0 0 132 | #define QSPI_1 1 133 | typedef union { 134 | struct { 135 | UC CSR_LSB; //Enable,Abort request,FTh 136 | UC CSR_CsIE; //Chip select ,interrupt enable,AMPS and PMM 137 | US CSR_Prescalar; 138 | UC CSR_Flag; //Flags 139 | UC CSR_FLevel; 140 | US dummy; 141 | } Field; 142 | 143 | UL value; 144 | } CSR_CONFG_TYPE; 145 | 146 | typedef union { 147 | struct { 148 | US DCR_ModeCHST :4, //level that Sclk takes between commands and Chip Select High Time 149 | DCR_FSize :5, //Flash memory size 150 | dummy1 :7; 151 | US dummy2; 152 | UI dummy3; 153 | } Field; 154 | 155 | UL value; 156 | } DCR_CONFG_TYPE; 157 | 158 | //Register address mapping 159 | #define QSPIReg(i) (*((volatile QSPI_REG_TYPE *)(QSPI_BASE_ADDR+ (0x100 * i)))) 160 | 161 | 162 | 163 | /* Function declaration section 164 | * 165 | * 166 | ***************************************************/ 167 | 168 | void qspi_initialise(UC qspi_number); 169 | void qspi_read_flash_register(UC qspi_number, UL address, UI dataLength, 170 | UC command, UC instr_line, UC data_line, UC *read_data); 171 | 172 | void qspi_instrTxt(UC qspi_number, UC instr_line, UC command); 173 | 174 | void qspi_write_flash_register(UC qspi_number, UL address, UI dataLength, 175 | UC command, UC instr_line, UC data_line, UC wr_data); 176 | 177 | void qspi_mem_write(UC qspi_number, UL Address, UI DataLength, UC command, 178 | UC instr_line, UC data_line, UC data_size, UC address_line, 179 | UC address_size, UC fifo_threshold, UC *write_data); 180 | 181 | void qspi_mem_read(UC qspi_number, UL Address, UI DataLength, UC command, 182 | UC instr_line, UC data_line, UC data_size, UC address_line, 183 | UC address_size, UC fifo_threshold, UC *read_data); 184 | 185 | UC qspi_wait_if_busy(UC qspi_number); 186 | 187 | void qspi_mem_erase(UC qspi_number, UL Address, UI DataLength, UC command, 188 | UC instr_line, UC address_line, UC address_size) ; 189 | 190 | void qspi_write_read_444P_adrsize3(UC qspi_number, UI Pages, UI address, 191 | UC Wfifo_thres, UC WData_size, UC Rfifo_thres, UC RData_size); 192 | void qspi_flash_read(UC qspi_number, UI RAddress, UI Rdata_len, UC i_line, 193 | UC d_line, UC d_size, UC addr_line, UC addr_size, UC fifo_thres,UC *read_data); 194 | void qspi_flash_write(UC qspi_number, UI WAddress, UI Wdata_len, UC i_line, 195 | UC d_line, UC d_size, UC addr_line, UC addr_size, UC fifo_thres,UC *wr_data); 196 | void qspi_flash_serase(UC qspi_number, UI SAddress, UI SData_len, UC i_line, 197 | UC d_line, UC addr_line, UC addr_size); 198 | void qspi_init_transfer(UC qspi_number, UI Clk_Prescalar, UC fifo_thres, 199 | UC Auto_poll_stop, UC Poll_Match); 200 | void flash_confg_444(UC qspi_number); 201 | void flash_busy_check(UC qspi_number, UC i_line, UC d_line); 202 | 203 | UC comparedata(UC *bWrData, UC *bRdData, UL wDataLength); 204 | void flash_read_id(UC qspi_number); 205 | void board_setup(UC qspi_number); 206 | void qspi_delay(UL count); 207 | 208 | 209 | #endif 210 | 211 | #endif 212 | 213 | -------------------------------------------------------------------------------- /drivers/interrupt.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file interrupt.c 3 | @brief Contains routines for Iinterrupt handler, IRQ enable functions 4 | @detail Includes software functions to enable, handling functions for intterrupt 5 | 6 | @authors Debayan Sutradhar (@rnayabed), Avra Mitra (@abhra0897) 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | 17 | #if __riscv_xlen == 64 18 | #define MAXIMUM_INTR_COUNT 64 19 | #else 20 | #define MAXIMUM_INTR_COUNT 32 21 | #endif 22 | 23 | #define read_const_csr(reg) ({ unsigned long __tmp; \ 24 | asm ("csrr %0, " #reg : "=r"(__tmp)); \ 25 | __tmp; }) 26 | 27 | 28 | extern volatile unsigned long INTERRUPT_Handler_0; 29 | extern volatile unsigned long trap_entry; 30 | 31 | void (*irq_table[MAXIMUM_INTR_COUNT])(void); 32 | void (*sw_irq_function)(void); 33 | 34 | 35 | /** @fn enable_irq 36 | @brief Enable processor interrupt and Global interrupt in machine mode. 37 | @details The function "set_csr" will set the external interrupt bit in MIE register and Machine mode interrupt in MSTATUS register. 38 | 39 | @param[in] No input parameter. 40 | @param[Out] No output parameter. 41 | */ 42 | void enable_irq(void) { 43 | set_csr(mie, MIP_MEIP); // Set MEIE bit in MIE register for Machine External Intr. 44 | set_csr(mstatus, MSTATUS_MIE); // Set global machine intr bit (3rd bit) in MSTATUS register. 45 | #if __riscv_xlen == 64 46 | //For 64 Bit processors 47 | write_csr(mtvec,(UL)&INTERRUPT_Handler_0); // Set MTVEC register with vector address. 48 | #else 49 | //For 32 Bit processors 50 | write_csr(mtvec,(UI)&INTERRUPT_Handler_0); // Set MTVEC register with vector address. 51 | #endif 52 | } 53 | 54 | /** @fn enable_sw_irq 55 | 56 | @brief Enable processor interrupt and Global interrupt in machine mode. 57 | @details The function "set_csr" will set the software interrupt bit in MIE register and Machine mode interrupt in MSTATUS register. 58 | 59 | @param[in] No input parameter. 60 | @param[Out] No output parameter. 61 | */ 62 | void enable_sw_irq(void) { 63 | #if __riscv_xlen == 64 64 | //For 64 Bit processors 65 | write_csr(mtvec,(UL)&INTERRUPT_Handler_0); // Set MTVEC register with vector address. 66 | 67 | #else 68 | //For32 Bit processors 69 | write_csr(mtvec,(UI)&INTERRUPT_Handler_0); // Set MTVEC register with vector address. 70 | 71 | #endif 72 | set_csr(mie, MIP_MSIP); // Set MSIE bit in MIE register for Machine SW intr. 73 | set_csr(mstatus, MSTATUS_MIE); // Set global machine intr bit (3rd bit) in MSTATUS register. 74 | clear_csr(mideleg, MIP_MSIP); 75 | 76 | } 77 | 78 | 79 | /** @fn disable_sw_irq 80 | 81 | @brief Disable machine software interrupt in MIE register 82 | @details 83 | 84 | @param[in] No input parameter. 85 | @param[Out] No output parameter. 86 | */ 87 | void disable_sw_irq(void) { 88 | 89 | clear_csr(mie, MIP_MSIP); // Clear MSIP bit in MIE register for Machine 90 | 91 | } 92 | 93 | 94 | /** @fn void interrupt_enable(UC intr_number) 95 | @brief Enable interrupt in controller. 96 | @details The interrupt enable register is set with the enable value of peripheral selected. 97 | 98 | @param[in] unsigned char intr_number: The number at which the periphral will interrupt 99 | @param[Out] No output parameter. 100 | */ 101 | 102 | void interrupt_enable(UC intr_number) 103 | { 104 | enable_irq(); // Enable global interrupt and external interrupt of the processor. 105 | PLIC_INTR_REGS.INTR_EN |= ((UL)1 << intr_number); // Enable interrupt for peripheral in interrupt controller. 106 | __asm__ __volatile__ ("fence"); 107 | } 108 | 109 | 110 | /** @fn void irq_register_handler(UC irq_no, void (*irq_handler)()) 111 | @brief Initialise peripheral interrupt handler to a table. 112 | @details Enable processor interrupt and Global interrupt in machine mode and init irq_table. 113 | @warning 114 | @param[in] No input parameter. 115 | @param[Out] No output parameter. 116 | */ 117 | void irq_register_handler(UC irq_no, void (*irq_handler)()){ 118 | //*irq_handler is function pointer to user defined intr handler 119 | irq_table[irq_no] = irq_handler; 120 | } 121 | 122 | /** @fn void sw_irq_register_handler(UC irq_no, void (*irq_handler)()) 123 | @brief Initialise peripheral interrupt handler to a table. 124 | @details Enable processor interrupt and Global interrupt in machine mode and init irq_table. 125 | @warning 126 | @param[in] No input parameter. 127 | @param[Out] No output parameter. 128 | */ 129 | void sw_irq_register_handler( void (*irq_handler)()){ 130 | //*irq_handler is function pointer to user defined intr handler 131 | sw_irq_function = irq_handler; 132 | } 133 | 134 | 135 | /** @fn interrupt_handler 136 | @brief Invoke the peripheral interrupt handler. 137 | @details The interrupt controller's status register is read to identify the interrupted peripheral and then the corresponding 138 | handler for the peripheral is invoked. 139 | @warning 140 | @param[in] No input parameter. 141 | @param[Out] No output parameter. 142 | */ 143 | void interrupt_handler(void){ 144 | void (*func_ptr)(); 145 | int mcause_val = 0, trap_type=0; 146 | 147 | #if __riscv_xlen == 64 148 | trap_type = (read_csr(mcause) >> 63); 149 | #else 150 | trap_type = (read_csr(mcause) >> 31); 151 | #endif 152 | 153 | if(trap_type) 154 | { //Interrupt 155 | mcause_val = ((read_csr(mcause) << 1)>>1); 156 | 157 | if(mcause_val == 3) 158 | { 159 | // Machine software interrupt 160 | #if __riscv_xlen == 64 161 | PLIC_SW_INTR_EN = 0; //OFF sw intr 162 | #else 163 | clear_csr(mip, MIP_MSIP); // Clear MSIP bit in MIP register for Machine 164 | #endif 165 | 166 | sw_irq_function(); // Invoke the peripheral handler as function pointer. 167 | } 168 | else 169 | { 170 | UL intr_status = PLIC_INTR_REGS.INTR_STATUS; 171 | 172 | for(UL i = 0; i < MAXIMUM_INTR_COUNT ; i++) 173 | { 174 | if ((intr_status >> i) & 1){ 175 | irq_table[i]();// Invoke the peripheral handler as function pointer. 176 | } 177 | } 178 | } 179 | } 180 | else 181 | { //Exception 182 | func_ptr = (void (*)()) (&trap_entry); //jump to exception handler 183 | func_ptr(); 184 | } 185 | } 186 | 187 | /** @fn generate_sw_irq 188 | @brief Generates machine mode software interrupt if already enabled 189 | @details 190 | @warning 191 | @param[in] No input parameter. 192 | @param[Out] No output parameter. 193 | */ 194 | 195 | 196 | void generate_sw_irq(void){ 197 | 198 | #if __riscv_xlen == 64 199 | PLIC_SW_INTR_EN = 1; //ON sw intr 200 | #else 201 | set_csr(mip, MIP_MSIP); // Set MSIP bit in MIP register for Machine SW intr. 202 | #endif 203 | 204 | } 205 | 206 | 207 | -------------------------------------------------------------------------------- /drivers/i2c.c: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | 3 | 4 | Project Name : MDP - Microprocessor Development Project 5 | Project Code : HD083D 6 | Created : 08-Nov-2019 7 | Filename : i2c.c 8 | Purpose : I2C Firmware 9 | Description : I2C routines 10 | Author(s) : Karthika P 11 | Email : karthikap@cdac.in 12 | 13 | See LICENSE for license details. 14 | ***************************************************/ 15 | 16 | /** 17 | @file i2c.c 18 | @brief Contains routines for I2C interface 19 | @detail Includes software functions to initialize, 20 | configure, write and read over I2C interface 21 | */ 22 | #include 23 | #include 24 | #include 25 | 26 | UL SYS_CLK; 27 | UL I2C_CLK; 28 | 29 | /** 30 | @fn void i2c_initialize(UC i2c_number) 31 | @brief I2C Initialization 32 | @details Initializes I2C Clock period registers 33 | @param[in] unsigned char(i2c_number--which i2c to be used) 34 | @param[Out] No ouput parameter. 35 | @return Void function. 36 | 37 | */ 38 | void i2c_initialize(UC i2c_number) { 39 | I2CReg(i2c_number).I2C_TXCLR = 0xFF; 40 | 41 | __asm__ __volatile__ ("fence"); 42 | US CH = SYS_CLK / (2 * I2C_CLK); 43 | I2CReg(i2c_number).I2C_CHL = ((UC) (CH & 0xFF)); 44 | //printf("CHL is %x", (I2CReg(i2c_number).I2C_CHL)); 45 | //printf("\n\r"); 46 | I2CReg(i2c_number).I2C_CHH = (UC) ((CH >> 8) & 0xFF); 47 | //printf("CHH is %x", (I2CReg(i2c_number).I2C_CHH)); 48 | //printf("\n\r"); 49 | US CHH = SYS_CLK / (4 * I2C_CLK); 50 | 51 | I2CReg(i2c_number).I2C_CHHL = ((UC) (CHH & 0xFF)); 52 | //printf("CHHL is %x", (I2CReg(i2c_number).I2C_CHHL)); 53 | //printf("\n\r"); 54 | I2CReg(i2c_number).I2C_CHHH = (UC) ((CHH >> 8) & 0xFF); 55 | //printf("CHHH is %x", (I2CReg(i2c_number).I2C_CHH)); 56 | //printf("\n\r"); 57 | __asm__ __volatile__ ("fence"); 58 | } 59 | 60 | /** 61 | @fn UC i2c_start(UC i2c_number, UC read_length, UC Read) 62 | @brief Generates Start Sequence for I2C 63 | @details Start sequence is setting start bit and read length in I2C control 64 | register for I2C operations. 65 | @param[in] unsigned char(i2c_number--which i2c to be used) 66 | @param[in] unsigned char (read_length). 67 | @param[in] unsigned char (Read).1 if Read operation and 0 if write operation 68 | @param[Out] No output parameters. 69 | @return -2 if read length is greater than 16 and return 0 when success 70 | */ 71 | 72 | UC i2c_start(UC i2c_number, UC read_length, UC Read) { 73 | if (read_length > 16) { 74 | printf("max read length supported is 16 \n\r"); 75 | return -2; //max read length 16 is supported 76 | } 77 | I2CReg(i2c_number).I2C_TXCLR = 0xFF; //clear TxFifo 78 | while (((I2CReg(i2c_number).I2C_SR0 & 0x08) != 0x08) 79 | || ((I2CReg(i2c_number).I2C_SR0 & 0x10) != 0x10)) 80 | ; //checks for transmission complete and TxFifo empty 81 | 82 | if (Read == 1) 83 | I2CReg(i2c_number).I2C_CR = ((read_length << 2) | 0x01); //Set Start bit for read;read_length=1 byte 84 | else 85 | I2CReg(i2c_number).I2C_CR = 0x01; //Set Start bit for write; 86 | 87 | __asm__ __volatile__ ("fence"); 88 | //printf("CR is %x",I2CReg(i2c_number).I2C_CR); 89 | //printf("\n\r"); 90 | while ((I2CReg(i2c_number).I2C_SR0 & 0x01) != 0x01) 91 | ; //check start sequence initiated 92 | return 0; 93 | } 94 | 95 | /** 96 | @fn void i2c_configure(UC i2c_number, UL System_Clock, UL I2C_Clock) 97 | @brief Configures I2C 98 | @details Configures I2C Clock period registers 99 | @param[in] unsigned char(i2c_number--which i2c to be used) 100 | @param[in] unsigned short(System_Clock,I2C_Clock) 101 | @param[Out] No output parameters. 102 | @return nil 103 | */ 104 | 105 | void i2c_configure(UC i2c_number, UL System_Clock, UL I2C_Clock) { 106 | I2C_CLK = I2C_Clock; 107 | SYS_CLK = System_Clock; 108 | i2c_initialize(i2c_number); 109 | } 110 | 111 | /** 112 | @fn UC i2c_data_write(UC i2c_number, UC *write_data, UC write_length) 113 | @brief Write data to transmit Fifo and checks for NACK 114 | @details Data/address to be transmitted is written into transmit fifo and checks NACK 115 | @param[in] unsigned char(i2c_number--which i2c to be used) 116 | @param[in] unsigned char(*write_data-->Data/Address to be transmitted) 117 | @param[in] unsigned char(*write_length-->Number of bytes to be written) 118 | @param[Out] No output parameters. 119 | @return 0 if ACK and 1 if NACK 120 | */ 121 | 122 | UC i2c_data_write(UC i2c_number, UC *write_data, UC write_length) { 123 | for (int i = 0; i < write_length; i++) { 124 | while ((I2CReg(i2c_number).I2C_SR0 & 0x04) == 0x04) 125 | ; //waits if TxFF full 126 | 127 | I2CReg(i2c_number).I2C_TxFF = *write_data; 128 | write_data++; 129 | __asm__ __volatile__ ("fence"); 130 | } 131 | 132 | while ((I2CReg(i2c_number).I2C_SR0 & 0x10) != 0x10) 133 | 134 | ; //wait for Transfer complete 135 | 136 | if ((I2CReg(i2c_number).I2C_SR1 & 0x01) == 0x01) { //checks NACK 137 | 138 | while ((I2CReg(i2c_number).I2C_SR0 & 0x02) != 0x02) 139 | ; //wait for stop bit to be set 140 | //printf("NACK rxd and stop bit set\n\r"); 141 | return 1; 142 | } else 143 | return 0; 144 | } 145 | 146 | /** 147 | @fn void i2c_stop(UC i2c_number) 148 | @brief Generates Stop Sequence for I2C 149 | @details Stop sequence is setting stop bit I2C control register for I2C operations. 150 | @param[in] unsigned char(i2c_number--which i2c to be used) 151 | @param[Out] No output parameters. 152 | @return Nil 153 | */ 154 | 155 | void i2c_stop(UC i2c_number) { 156 | 157 | I2CReg(i2c_number).I2C_CR = 0x02; //Set Stop bit; 158 | __asm__ __volatile__ ("fence"); 159 | while ((I2CReg(i2c_number).I2C_SR0 & 0x02) != 0x02) 160 | ; //check stop sequence initiated 161 | 162 | } 163 | 164 | /** 165 | @fn UC i2c_data_read(UC i2c_number, UC *read_data, UC read_length) 166 | @brief Read data from I2C device 167 | @details After Rx Complete,read data from fifo till fifo is empty 168 | @param[in] unsigned char(i2c_number--which i2c to be used) 169 | @param[in] unsigned char(*read_data--data read from EEPROM) 170 | @param[in] unsigned char(read_length--no:of bytes to read) 171 | @param[Out] No output parameters. 172 | @return unsigned char (Data-->Data from I2C device) 173 | */ 174 | 175 | UC i2c_data_read(UC i2c_number, UC *read_data, UC read_length) { 176 | if (read_length > 16) { 177 | printf("max read length supported is 16 \n\r"); 178 | return -2; //max read length 16 is supported 179 | } 180 | while ((I2CReg(i2c_number).I2C_SR0 & 0x80) != 0x80) 181 | ; //checks for RX complete 182 | for (int i = 0; i < read_length; i++) { 183 | 184 | while ((I2CReg(i2c_number).I2C_SR0 & 0x40) == 0x40) 185 | ; //wait if RXfifo empty 186 | *read_data = I2CReg(i2c_number).I2C_RxFF; //reading RXFF 187 | read_data++; 188 | //printf("data is %x",Data); 189 | //printf("\n\r"); 190 | } 191 | 192 | while ((I2CReg(i2c_number).I2C_SR0 & 0x02) != 0x02) 193 | ; //wait for stop bit to be set 194 | return 0; 195 | 196 | } 197 | 198 | /** @fn void I2C_enable_intr(UC i2c_number,UC tx_intr,UC rx_intr) 199 | * @brief Enable I2C interrupts. 200 | * @details Enable the I2C Tx and Rx interrupt. 201 | 202 | * @param[in] unsigned char,unsigned char,unsigned char 203 | * @param[Out] No output parameter 204 | */ 205 | void I2C_enable_intr(UC i2c_number,UC tx_intr,UC rx_intr) 206 | { 207 | I2CReg(i2c_number).I2C_IER = ((rx_intr << 2) | (tx_intr << 1)|01); 208 | __asm__ __volatile__ ("fence"); 209 | } 210 | 211 | /** @fn int I2C_intr_handler(UC I2C_number) 212 | * @brief Interrupt handler. 213 | * @details Reads I2C controllers status register to distinguish which type of interrupt has occurred. 214 | 215 | * @param[in] unsigned char 216 | * @param[Out] Returns 1 if Tx intr occurs, 2 if Rx intr occurs. 217 | */ 218 | int I2C_intr_handler(UC I2C_number) { 219 | UC status = 0; 220 | 221 | status = I2CReg(I2C_number).I2C_SR1; 222 | if((status & 0x02)==0x02) // I2C TX intr occurred. 223 | return 1; 224 | else if((status & 0x03)==0x03) 225 | return 2; // I2C RX intr occurred. 226 | } 227 | 228 | -------------------------------------------------------------------------------- /common/crt.S: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Project Name : MDP - Microprocessor Development Project 4 | Project Code : HD083D 5 | Created : 07-Nov-2019 6 | Filename : crt.S 7 | Purpose : Initialization 8 | Description : Register initilization and start file for 9 | programs. 10 | Author(s) : Premjith A V 11 | Email : premjith@cdac.in 12 | 13 | See LICENSE for license details. 14 | ******************************************************************************/ 15 | 16 | /** 17 | @file crt.S 18 | @brief Initialization function 19 | @detail Register initilization and start file for programs. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #if __riscv_xlen == 64 26 | # define LREG ld 27 | # define SREG sd 28 | # define REGBYTES 8 29 | #else 30 | # define LREG lw 31 | # define SREG sw 32 | # define REGBYTES 4 33 | #endif 34 | 35 | .section ".text.init" 36 | .globl _start 37 | 38 | _start: 39 | li x1, 0 40 | li x2, 0 41 | li x3, 0 42 | li x4, 0 43 | li x5, 0 44 | li x6, 0 45 | li x7, 0 46 | li x8, 0 47 | li x9, 0 48 | li x10,0 49 | li x11,0 50 | li x12,0 51 | li x13,0 52 | li x14,0 53 | li x15,0 54 | li x16,0 55 | li x17,0 56 | li x18,0 57 | li x19,0 58 | li x20,0 59 | li x21,0 60 | li x22,0 61 | li x23,0 62 | li x24,0 63 | li x25,0 64 | li x26,0 65 | li x27,0 66 | li x28,0 67 | li x29,0 68 | li x30,0 69 | li x31,0 70 | 71 | # enable FPU and accelerator if present 72 | #li t0, MSTATUS_FS | MSTATUS_XS 73 | #csrs mstatus, t0 74 | 75 | # make sure XLEN agrees with compilation choice 76 | li t0, 1 77 | slli t0, t0, 31 78 | #if __riscv_xlen == 64 79 | bgez t0, 1f 80 | #else 81 | bltz t0, 1f 82 | #endif 83 | 2: 84 | //li a0, 1 85 | //sw a0, tohost, t0 86 | j 2b 87 | 1: 88 | 89 | #ifdef __riscv_flen 90 | # initialize FPU if we have one 91 | la t0, 1f 92 | csrw mtvec, t0 93 | 94 | fssr x0 95 | fmv.s.x f0, x0 96 | fmv.s.x f1, x0 97 | fmv.s.x f2, x0 98 | fmv.s.x f3, x0 99 | fmv.s.x f4, x0 100 | fmv.s.x f5, x0 101 | fmv.s.x f6, x0 102 | fmv.s.x f7, x0 103 | fmv.s.x f8, x0 104 | fmv.s.x f9, x0 105 | fmv.s.x f10,x0 106 | fmv.s.x f11,x0 107 | fmv.s.x f12,x0 108 | fmv.s.x f13,x0 109 | fmv.s.x f14,x0 110 | fmv.s.x f15,x0 111 | fmv.s.x f16,x0 112 | fmv.s.x f17,x0 113 | fmv.s.x f18,x0 114 | fmv.s.x f19,x0 115 | fmv.s.x f20,x0 116 | fmv.s.x f21,x0 117 | fmv.s.x f22,x0 118 | fmv.s.x f23,x0 119 | fmv.s.x f24,x0 120 | fmv.s.x f25,x0 121 | fmv.s.x f26,x0 122 | fmv.s.x f27,x0 123 | fmv.s.x f28,x0 124 | fmv.s.x f29,x0 125 | fmv.s.x f30,x0 126 | fmv.s.x f31,x0 127 | 1: 128 | #endif 129 | 130 | # initialize trap vector 131 | la t0, trap_entry 132 | csrw mtvec, t0 133 | 134 | # initialize global pointer 135 | .option push 136 | .option norelax 137 | la gp, __global_pointer$ 138 | .option pop 139 | 140 | la tp, _end + 63 141 | and tp, tp, -64 142 | 143 | #Initialize flag for waiting till core 0 completes program download 144 | 145 | # get core id 146 | csrr a0, mhartid 147 | li a1, 1 148 | 1:bgeu a0, a1, 1b 149 | 150 | #clear bss,sbss 151 | la a3, _bss_start 152 | la a4, _bss_end 153 | 1: 154 | sw zero,0(a3) 155 | addi a3,a3,4 156 | bleu a3,a4, 1b 157 | 158 | # give each core 16KB of stack + TLS 159 | #define STKSHIFT 15 160 | sll a2, a0, STKSHIFT 161 | add tp, tp, a2 162 | add sp, a0, 1 163 | sll sp, sp, STKSHIFT 164 | add sp, sp, tp 165 | 166 | j _init 167 | 168 | .align 2 169 | .globl trap_entry 170 | trap_entry: 171 | addi sp, sp, -272 172 | 173 | SREG x1, 1*REGBYTES(sp) 174 | SREG x2, 2*REGBYTES(sp) 175 | SREG x3, 3*REGBYTES(sp) 176 | SREG x4, 4*REGBYTES(sp) 177 | SREG x5, 5*REGBYTES(sp) 178 | SREG x6, 6*REGBYTES(sp) 179 | SREG x7, 7*REGBYTES(sp) 180 | SREG x8, 8*REGBYTES(sp) 181 | SREG x9, 9*REGBYTES(sp) 182 | SREG x10, 10*REGBYTES(sp) 183 | SREG x11, 11*REGBYTES(sp) 184 | SREG x12, 12*REGBYTES(sp) 185 | SREG x13, 13*REGBYTES(sp) 186 | SREG x14, 14*REGBYTES(sp) 187 | SREG x15, 15*REGBYTES(sp) 188 | SREG x16, 16*REGBYTES(sp) 189 | SREG x17, 17*REGBYTES(sp) 190 | SREG x18, 18*REGBYTES(sp) 191 | SREG x19, 19*REGBYTES(sp) 192 | SREG x20, 20*REGBYTES(sp) 193 | SREG x21, 21*REGBYTES(sp) 194 | SREG x22, 22*REGBYTES(sp) 195 | SREG x23, 23*REGBYTES(sp) 196 | SREG x24, 24*REGBYTES(sp) 197 | SREG x25, 25*REGBYTES(sp) 198 | SREG x26, 26*REGBYTES(sp) 199 | SREG x27, 27*REGBYTES(sp) 200 | SREG x28, 28*REGBYTES(sp) 201 | SREG x29, 29*REGBYTES(sp) 202 | SREG x30, 30*REGBYTES(sp) 203 | SREG x31, 31*REGBYTES(sp) 204 | 205 | csrr a0, mcause 206 | csrr a1, mepc 207 | mv a2, sp 208 | jal handle_trap 209 | csrw mepc, a0 210 | 211 | # Remain in M-mode after eret 212 | li t0, MSTATUS_MPP 213 | csrs mstatus, t0 214 | 215 | LREG x1, 1*REGBYTES(sp) 216 | LREG x2, 2*REGBYTES(sp) 217 | LREG x3, 3*REGBYTES(sp) 218 | LREG x4, 4*REGBYTES(sp) 219 | LREG x5, 5*REGBYTES(sp) 220 | LREG x6, 6*REGBYTES(sp) 221 | LREG x7, 7*REGBYTES(sp) 222 | LREG x8, 8*REGBYTES(sp) 223 | LREG x9, 9*REGBYTES(sp) 224 | LREG x10, 10*REGBYTES(sp) 225 | LREG x11, 11*REGBYTES(sp) 226 | LREG x12, 12*REGBYTES(sp) 227 | LREG x13, 13*REGBYTES(sp) 228 | LREG x14, 14*REGBYTES(sp) 229 | LREG x15, 15*REGBYTES(sp) 230 | LREG x16, 16*REGBYTES(sp) 231 | LREG x17, 17*REGBYTES(sp) 232 | LREG x18, 18*REGBYTES(sp) 233 | LREG x19, 19*REGBYTES(sp) 234 | LREG x20, 20*REGBYTES(sp) 235 | LREG x21, 21*REGBYTES(sp) 236 | LREG x22, 22*REGBYTES(sp) 237 | LREG x23, 23*REGBYTES(sp) 238 | LREG x24, 24*REGBYTES(sp) 239 | LREG x25, 25*REGBYTES(sp) 240 | LREG x26, 26*REGBYTES(sp) 241 | LREG x27, 27*REGBYTES(sp) 242 | LREG x28, 28*REGBYTES(sp) 243 | LREG x29, 29*REGBYTES(sp) 244 | LREG x30, 30*REGBYTES(sp) 245 | LREG x31, 31*REGBYTES(sp) 246 | 247 | addi sp, sp, 272 248 | mret 249 | 250 | .align 2 251 | .section .INTERRUPT_isr_sect_0,"ax",@progbits 252 | .globl INTERRUPT_Handler_0 253 | INTERRUPT_Handler_0: 254 | addi sp, sp, -272 255 | 256 | SREG x1, 1*REGBYTES(sp) 257 | SREG x2, 2*REGBYTES(sp) 258 | SREG x3, 3*REGBYTES(sp) 259 | SREG x4, 4*REGBYTES(sp) 260 | SREG x5, 5*REGBYTES(sp) 261 | SREG x6, 6*REGBYTES(sp) 262 | SREG x7, 7*REGBYTES(sp) 263 | SREG x8, 8*REGBYTES(sp) 264 | SREG x9, 9*REGBYTES(sp) 265 | SREG x10, 10*REGBYTES(sp) 266 | SREG x11, 11*REGBYTES(sp) 267 | SREG x12, 12*REGBYTES(sp) 268 | SREG x13, 13*REGBYTES(sp) 269 | SREG x14, 14*REGBYTES(sp) 270 | SREG x15, 15*REGBYTES(sp) 271 | SREG x16, 16*REGBYTES(sp) 272 | SREG x17, 17*REGBYTES(sp) 273 | SREG x18, 18*REGBYTES(sp) 274 | SREG x19, 19*REGBYTES(sp) 275 | SREG x20, 20*REGBYTES(sp) 276 | SREG x21, 21*REGBYTES(sp) 277 | SREG x22, 22*REGBYTES(sp) 278 | SREG x23, 23*REGBYTES(sp) 279 | SREG x24, 24*REGBYTES(sp) 280 | SREG x25, 25*REGBYTES(sp) 281 | SREG x26, 26*REGBYTES(sp) 282 | SREG x27, 27*REGBYTES(sp) 283 | SREG x28, 28*REGBYTES(sp) 284 | SREG x29, 29*REGBYTES(sp) 285 | SREG x30, 30*REGBYTES(sp) 286 | SREG x31, 31*REGBYTES(sp) 287 | 288 | /*csrr a0, mcause 289 | csrr a1, mepc 290 | mv a2, sp*/ 291 | jal interrupt_handler 292 | 293 | /*# Remain in M-mode after eret 294 | li t0, MSTATUS_MPP 295 | csrs mstatus, t0*/ 296 | 297 | LREG x1, 1*REGBYTES(sp) 298 | LREG x2, 2*REGBYTES(sp) 299 | LREG x3, 3*REGBYTES(sp) 300 | LREG x4, 4*REGBYTES(sp) 301 | LREG x5, 5*REGBYTES(sp) 302 | LREG x6, 6*REGBYTES(sp) 303 | LREG x7, 7*REGBYTES(sp) 304 | LREG x8, 8*REGBYTES(sp) 305 | LREG x9, 9*REGBYTES(sp) 306 | LREG x10, 10*REGBYTES(sp) 307 | LREG x11, 11*REGBYTES(sp) 308 | LREG x12, 12*REGBYTES(sp) 309 | LREG x13, 13*REGBYTES(sp) 310 | LREG x14, 14*REGBYTES(sp) 311 | LREG x15, 15*REGBYTES(sp) 312 | LREG x16, 16*REGBYTES(sp) 313 | LREG x17, 17*REGBYTES(sp) 314 | LREG x18, 18*REGBYTES(sp) 315 | LREG x19, 19*REGBYTES(sp) 316 | LREG x20, 20*REGBYTES(sp) 317 | LREG x21, 21*REGBYTES(sp) 318 | LREG x22, 22*REGBYTES(sp) 319 | LREG x23, 23*REGBYTES(sp) 320 | LREG x24, 24*REGBYTES(sp) 321 | LREG x25, 25*REGBYTES(sp) 322 | LREG x26, 26*REGBYTES(sp) 323 | LREG x27, 27*REGBYTES(sp) 324 | LREG x28, 28*REGBYTES(sp) 325 | LREG x29, 29*REGBYTES(sp) 326 | LREG x30, 30*REGBYTES(sp) 327 | LREG x31, 31*REGBYTES(sp) 328 | 329 | addi sp, sp, 272 330 | mret 331 | 332 | .section ".tdata.begin" 333 | .globl _tdata_begin 334 | _tdata_begin: 335 | 336 | .section ".tdata.end" 337 | .globl _tdata_end 338 | _tdata_end: 339 | 340 | .section ".tbss.end" 341 | .globl _tbss_end 342 | _tbss_end: 343 | 344 | 345 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # SPDX-License-Identifier: MIT 4 | # Linux Setup script 5 | # Authors : Debayan Sutradhar (@rnayabed) 6 | 7 | VERSION=0.1 8 | 9 | CREATE_MINICOM_CONFIG=1 10 | MINICOM_CONFIG=/etc/minirc.aries 11 | 12 | WEBSITE_URL=https://github.com/rnayabed/taurus.git 13 | LICENSE_URL=https://github.com/rnayabed/taurus/blob/master/LICENSE 14 | CHANGES_URL=https://github.com/rnayabed/taurus/blob/master/README.md#comparison-with-official-sdk 15 | 16 | SOURCE_PATH=`dirname -- $(readlink -f "${BASH_SOURCE}")` 17 | BUILD_PATH="${SOURCE_PATH}/build" 18 | BUILD_TYPE=Debug 19 | BUILD_SYSTEM="Unix Makefiles" 20 | 21 | VALID_TARGET_BOARDS=("ARIES_V2" "ARIES_V3" "ARIES_MICRO_V1" "ARIES_IOT_V1") 22 | VALID_TARGET_SOCS=("THEJAS32" "THEJAS64" "CDACFPGA") 23 | 24 | 25 | usage() { 26 | printf " 27 | Usage: [-tb | --target-board] [-ts | --target-soc] 28 | [-tt | --target-triplet] [-tp | --toolchain-path] 29 | [-ip | --install-path] [-vp | --vegadude-path] 30 | [-nm | --no-minicom] 31 | [-h | --help] 32 | 33 | Option Summary: 34 | -tb | --target-board Required if --target-soc not provided. 35 | Set the target development board to 36 | build Taurus for. Adds extra optimisations 37 | for board if available. 38 | Valid targets are: 39 | %s 40 | 41 | -ts | --target-soc Required if --target-board not provided. 42 | Set the target System-on-Chip to build 43 | Taurus for. 44 | Valid targets are: 45 | %s 46 | 47 | -tt | --target-triplet Required. RISC-V GNU Compiler Target 48 | triplet. 49 | Example: 'riscv64-unknown-elf' 50 | 51 | -tp | --toolchain-path Optional. Specify the absolute path of 52 | toolchain if it is not present in PATH. 53 | 54 | -ip | --install-path Optional. Path where Taurus will be 55 | installed. 56 | 57 | -vp | --vegadude-path Optional. Provide vegadude path for taurus integration. 58 | Not required if vegadude is already present in PATH. 59 | 60 | -nm | --no-minicom Optional. Do not create minicom 61 | configuration file. Configuration is 62 | created if not specified. 63 | 64 | -h --help Print this message. 65 | " "${VALID_TARGET_BOARDS[*]}" "${VALID_TARGET_SOCS[*]}" 66 | } 67 | 68 | if [[ $# -eq 0 ]]; then 69 | usage 70 | exit 1 71 | fi 72 | 73 | while :; do 74 | case "${1-}" in 75 | -tb | --target-board) 76 | TAURUS_TARGET_BOARD="${2-}" 77 | shift 78 | ;; 79 | -ts | --target-soc) 80 | TAURUS_TARGET_SOC="${2-}" 81 | shift 82 | ;; 83 | -tt | --target-triplet) 84 | TAURUS_TARGET_TRIPLET="${2-}" 85 | shift 86 | ;; 87 | -tp | --toolchain-path) 88 | TAURUS_TOOLCHAIN_PATH="${2-}" 89 | shift 90 | ;; 91 | -ip | --install-path) 92 | TAURUS_INSTALL_PATH="${2-}" 93 | shift 94 | ;; 95 | -vp | --vegadude-path) 96 | TAURUS_VEGADUDE_PATH="${2-}" 97 | shift 98 | ;; 99 | -nm | --no-minicom) 100 | CREATE_MINICOM_CONFIG=0 101 | ;; 102 | *) 103 | if [[ ! -z "${1-}" ]]; then 104 | printf "Invalid option %s\n" "${1-}" 105 | printf "Run with --help for usage.\n" 106 | exit 1 107 | else 108 | break 109 | fi 110 | ;; 111 | esac 112 | shift 113 | done 114 | 115 | if [[ ! -z ${TAURUS_TARGET_BOARD+x} ]] && [[ ! -z ${TAURUS_TARGET_SOC+x} ]]; then 116 | printf "You cannot provide target board and target SoC at the same time.\n" 117 | ERROR=1 118 | elif [[ -z ${TAURUS_TARGET_BOARD+x} ]] && [[ -z ${TAURUS_TARGET_SOC+x} ]]; then 119 | printf "Target board or target SoC required.\n" 120 | ERROR=1 121 | fi 122 | 123 | if [[ ! -z ${TAURUS_TARGET_BOARD+x} ]] && [[ ! " ${VALID_TARGET_BOARDS[*]} " =~ " $TAURUS_TARGET_BOARD " ]]; then 124 | printf "Invalid target board provided. 125 | Valid target boards are %s\n" "${VALID_TARGET_BOARDS[*]}" 126 | ERROR=1 127 | fi 128 | 129 | if [[ ! -z ${TAURUS_TARGET_SOC+x} ]] && [[ ! " ${VALID_TARGET_SOCS[*]} " =~ " $TAURUS_TARGET_SOC " ]]; then 130 | printf "Invalid target SoC provided. 131 | Valid target SoCs are %s\n" "${VALID_TARGET_SOCS[*]}" 132 | ERROR=1 133 | fi 134 | 135 | if [[ -z ${TAURUS_TARGET_TRIPLET+x} ]]; then 136 | printf "Target triplet required.\n" 137 | ERROR=1 138 | fi 139 | 140 | if [[ $ERROR -eq 1 ]]; then 141 | printf "Run with --help for usage.\n" 142 | exit 1 143 | fi 144 | 145 | 146 | printf " 147 | 148 | ***** ***** 149 | **** **** 150 | **** **** 151 | ***** ***** 152 | ************ 153 | ************** 154 | *** *** 155 | *** *** 156 | *** *** 157 | *** *** 158 | ***** ***** 159 | ********* 160 | 161 | Taurus SDK - %s 162 | 163 | 164 | Website 165 | %s 166 | 167 | To know full list of changes compared to the original SDK, 168 | please visit 169 | %s 170 | 171 | This program comes with ABSOLUTELY NO WARRANTY. 172 | This is free software, and you are welcome to redistribute it 173 | under certain conditions. 174 | 175 | Full license can be found in the 'LICENSE' file provided with the SDK. 176 | The license can also be viewed by visiting %s 177 | 178 | " "$VERSION" "$WEBSITE_URL" "$CHANGES_URL" "$LICENSE_URL" 179 | 180 | 181 | com="cmake -B \"${BUILD_PATH}\" -S \"${SOURCE_PATH}\" -G \"${BUILD_SYSTEM}\" -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DTAURUS_TARGET_TRIPLET=${TAURUS_TARGET_TRIPLET} " 182 | 183 | if [[ ! -z ${TAURUS_TARGET_BOARD+x} ]]; then 184 | com+="-DTAURUS_TARGET_BOARD=${TAURUS_TARGET_BOARD} " 185 | TAURUS_TARGET=${TAURUS_TARGET_BOARD} 186 | else 187 | com+="-DTAURUS_TARGET_SOC=${TAURUS_TARGET_SOC} " 188 | TAURUS_TARGET=${TAURUS_TARGET_SOC} 189 | fi 190 | 191 | if [[ ! -z ${TAURUS_TOOLCHAIN_PATH+x} ]]; then 192 | com+="-DTAURUS_TOOLCHAIN_PATH=${TAURUS_TOOLCHAIN_PATH}" 193 | fi 194 | 195 | if [[ ! -z ${TAURUS_INSTALL_PATH+x} ]]; then 196 | com+="-DCMAKE_INSTALL_PREFIX=${TAURUS_INSTALL_PATH}" 197 | fi 198 | 199 | if [[ ! -z ${TAURUS_VEGADUDE_PATH+x} ]]; then 200 | com+="-DTAURUS_VEGADUDE_PATH=${TAURUS_VEGADUDE_PATH}" 201 | fi 202 | 203 | printf "\nRemoving old files ...\n" 204 | 205 | rm -rf "${BUILD_PATH}" 206 | 207 | printf "\nGenerating build system ...\n" 208 | 209 | eval $com 210 | 211 | if [[ $? -ne 0 ]]; then 212 | printf "Failed to generate build system for Taurus SDK.\n" 213 | exit 1 214 | fi 215 | 216 | printf "\nCompiling ...\n" 217 | 218 | cmake --build "${BUILD_PATH}" 219 | 220 | if [[ $? -ne 0 ]]; then 221 | printf "Failed to compile Taurus SDK.\n" 222 | exit 1 223 | fi 224 | 225 | printf "\nInstalling ...\n" 226 | 227 | if [[ -z ${TAURUS_INSTALL_PATH+x} ]] || [[ -r "${TAURUS_INSTALL_PATH}" ]]; then 228 | printf "\nAdditional permissions required. You might be asked for root password.\n\n" 229 | sudo make -C "${BUILD_PATH}" install 230 | else 231 | make -C "${BUILD_PATH}" install 232 | fi 233 | 234 | if [[ $? -ne 0 ]]; then 235 | printf "Failed to install Taurus SDK.\n" 236 | exit 1 237 | fi 238 | 239 | 240 | 241 | if [[ "$CREATE_MINICOM_CONFIG" -eq 1 ]]; then 242 | printf "\nCreating Minicom configuration file\n" 243 | printf "# Taurus SDK - Minicom Configuration for CDAC Vega 244 | pu port /dev/ttyUSB0 245 | pu baudrate 115200 246 | pu bits 8 247 | pu parity N 248 | pu stopbits 1 249 | pu rtscts No 250 | " | sudo tee ${MINICOM_CONFIG} > /dev/null 251 | 252 | if [[ $? -ne 0 ]]; then 253 | printf "Failed to create Minicom configuration file\n" 254 | exit 1 255 | fi 256 | 257 | fi 258 | 259 | 260 | printf "\n===================================================================== 261 | Taurus SDK %s for %s is now ready to use. 262 | " "$VERSION" "$TAURUS_TARGET" 263 | 264 | if [[ ${CREATE_MINICOM_CONFIG} -eq 1 ]]; then 265 | printf "\nMinicom configuration has also been created at 266 | %s 267 | You can access it by running 'sudo minicom aries'. 268 | You may also add yourself in the "dialout" user group to use 269 | minicom without root permissions.\n" "$MINICOM_CONFIG" 270 | fi 271 | 272 | printf " 273 | For queries, issues, etc. visit 274 | %s 275 | 276 | Enjoy! 277 | =====================================================================\n" "${WEBSITE_URL}" 278 | -------------------------------------------------------------------------------- /setup.bat: -------------------------------------------------------------------------------- 1 | :: SPDX-License-Identifier: MIT 2 | :: Windows Setup Script 3 | :: Authors : Debayan Sutradhar (@rnayabed) 4 | 5 | @echo off 6 | 7 | set "VERSION=0.1" 8 | 9 | set "WEBSITE_URL=https://github.com/rnayabed/taurus.git" 10 | set "LICENSE_URL=https://github.com/rnayabed/taurus/blob/master/LICENSE" 11 | set "CHANGES_URL=https://github.com/rnayabed/taurus/blob/master/README.md#comparison-with-official-sdk" 12 | 13 | set "SOURCE_PATH=%~dp0" 14 | set "SOURCE_PATH=%SOURCE_PATH:\=/%" 15 | set "BUILD_PATH=%SOURCE_PATH%/build" 16 | set "BUILD_TYPE=Debug" 17 | set "BUILD_SYSTEM=Ninja" 18 | 19 | set "VALID_TARGET_BOARDS=ARIES_V2 ARIES_V3 ARIES_MICRO_V1 ARIES_IOT_V1" 20 | set "VALID_TARGET_SOCS=THEJAS32 THEJAS64 CDACFPGA" 21 | 22 | set "TAURUS_TARGET_BOARD=" 23 | set "TAURUS_TARGET_SOC=" 24 | set "TAURUS_TARGET_TRIPLET=" 25 | set "TAURUS_TOOLCHAIN_PATH=" 26 | set "TAURUS_INSTALL_PATH=" 27 | set "TAURUS_VEGADUDE_PATH=" 28 | 29 | for %%A in (%*) do ( 30 | goto :parse_args 31 | ) 32 | 33 | call :usage 34 | exit /b 1 35 | 36 | 37 | :parse_args 38 | 39 | if "%~1"=="-tb" ( goto :set_target_board ) 40 | if "%~1"=="--target-board" ( goto :set_target_board ) 41 | 42 | if "%~1"=="-ts" ( goto :set_target_soc ) 43 | if "%~1"=="--target-soc" ( goto :set_target_soc ) 44 | 45 | if "%~1"=="-tt" ( goto :set_target_triplet ) 46 | if "%~1"=="--target-triplet" ( goto :set_target_triplet ) 47 | 48 | if "%~1"=="-tp" ( goto :set_toolchain_path ) 49 | if "%~1"=="--toolchain-path" ( goto :set_toolchain_path ) 50 | 51 | if "%~1"=="-ip" ( goto :set_install_path ) 52 | if "%~1"=="--install-path" ( goto :set_install_path ) 53 | 54 | if "%~1"=="-vp" ( goto :set_vegadude_path ) 55 | if "%~1"=="--vegadude-path" ( goto :set_vegadude_path ) 56 | 57 | if not "%~1"=="" ( 58 | echo Invalid option %~1 59 | echo Run with --help for usage. 60 | exit /b 1 61 | ) 62 | 63 | goto :validate_inputs 64 | 65 | :parse_args_tail 66 | shift 67 | shift 68 | goto :parse_args 69 | 70 | :validate_inputs 71 | 72 | set ERROR=0 73 | 74 | set TARGET_ARGS=0 75 | if not "%TAURUS_TARGET_BOARD%"=="" ( set /A TARGET_ARGS+=1 ) 76 | if not "%TAURUS_TARGET_SOC%"=="" ( set /A TARGET_ARGS+=1 ) 77 | 78 | if %TARGET_ARGS% equ 0 ( 79 | echo Target board or target SoC required. 80 | set /A ERROR = 1 81 | ) 82 | if %TARGET_ARGS% equ 2 ( 83 | echo You cannot provide target board and target SoC at the same time. 84 | set /A ERROR = 1 85 | ) 86 | 87 | if not "%TAURUS_TARGET_BOARD%"=="" ( 88 | for %%A in (%VALID_TARGET_BOARDS%) do ( 89 | if "%TAURUS_TARGET_BOARD%"=="%%A" ( goto :validate_inputs_tail ) 90 | ) 91 | echo Invalid target board provided. 92 | echo Valid target boards are %VALID_TARGET_BOARDS% 93 | set /A ERROR = 1 94 | ) else ( 95 | for %%A in (%VALID_TARGET_SOCS%) do ( 96 | if "%TAURUS_TARGET_SOC%"=="%%A" ( goto :validate_inputs_tail ) 97 | ) 98 | echo Invalid target SoC provided. 99 | echo Valid target SoCs are %VALID_TARGET_SOCS% 100 | set /A ERROR = 1 101 | ) 102 | 103 | if "%TAURUS_TARGET_TRIPLET%"=="" ( 104 | echo Target triplet required. 105 | set /A ERROR = 1 106 | ) 107 | 108 | :validate_inputs_tail 109 | if %ERROR% equ 1 ( 110 | echo Run with --help for usage. 111 | exit /b 1 112 | ) 113 | 114 | 115 | 116 | 117 | echo: 118 | echo: 119 | echo ***** ***** 120 | echo **** **** 121 | echo **** **** 122 | echo ***** ***** 123 | echo ************ 124 | echo ************** 125 | echo *** *** 126 | echo *** *** 127 | echo *** *** 128 | echo *** *** 129 | echo ***** ***** 130 | echo ********* 131 | echo: 132 | echo Taurus SDK - %VERSION% 133 | echo: 134 | echo: 135 | echo Website 136 | echo %WEBSITE_URL% 137 | echo: 138 | echo To know full list of changes compared to the original SDK, 139 | echo please visit 140 | echo %CHANGES_URL% 141 | echo: 142 | echo This program comes with ABSOLUTELY NO WARRANTY. 143 | echo This is free software, and you are welcome to redistribute it 144 | echo under certain conditions. 145 | echo: 146 | echo Full license can be found in the 'LICENSE' file provided with the SDK. 147 | echo The license can also be viewed by visiting %LICENSE_URL% 148 | echo: 149 | 150 | set "com=cmake -B "%BUILD_PATH%" -S "%SOURCE_PATH%" -G "%BUILD_SYSTEM%" -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DTAURUS_TARGET_TRIPLET=%TAURUS_TARGET_TRIPLET% " 151 | 152 | if not "%TAURUS_TARGET_BOARD%"=="" ( 153 | set "com=%com%-DTAURUS_TARGET_BOARD=%TAURUS_TARGET_BOARD% " 154 | set "TAURUS_TARGET=%TAURUS_TARGET_BOARD%" 155 | ) else ( 156 | set "com=%com%-DTAURUS_TARGET_SOC=%TAURUS_TARGET_SOC% " 157 | set "TAURUS_TARGET=%TAURUS_TARGET_SOC%" 158 | ) 159 | 160 | if not "%TAURUS_TOOLCHAIN_PATH%"=="" ( 161 | set "com=%com%-DTAURUS_TOOLCHAIN_PATH="%TAURUS_TOOLCHAIN_PATH%" " 162 | ) 163 | 164 | if not "%TAURUS_INSTALL_PATH%"=="" ( 165 | set "com=%com%-DCMAKE_INSTALL_PREFIX="%TAURUS_INSTALL_PATH%" " 166 | ) 167 | 168 | if not "%TAURUS_VEGADUDE_PATH%"=="" ( 169 | set "com=%com%-DTAURUS_VEGADUDE_PATH="%TAURUS_VEGADUDE_PATH%" " 170 | ) 171 | 172 | echo: 173 | echo Removing old files ... 174 | 175 | rmdir /S /Q "%BUILD_PATH%" 176 | 177 | echo: 178 | echo Generating build system ... 179 | 180 | %com% || goto :failed_to_generate_build_system 181 | 182 | echo: 183 | echo Compiling ... 184 | 185 | cmake --build "%BUILD_PATH%" || goto :failed_to_compile 186 | 187 | echo: 188 | echo Installing ... 189 | 190 | cmake --install "%BUILD_PATH%" || goto :failed_to_install 191 | 192 | echo: 193 | echo ===================================================================== 194 | echo Taurus SDK %VERSION% for %TAURUS_TARGET% is now ready to use. 195 | echo: 196 | echo For queries, issues, etc. visit 197 | echo %WEBSITE_URL% 198 | echo: 199 | echo Enjoy! 200 | echo ===================================================================== 201 | 202 | exit /b 0 203 | 204 | 205 | 206 | 207 | 208 | :failed_to_generate_build_system 209 | echo: 210 | echo Failed to generate build system for Taurus SDK. 211 | exit /b 1 212 | 213 | :failed_to_compile 214 | echo: 215 | echo Failed to compile Taurus SDK. 216 | exit /b 1 217 | 218 | :failed_to_install 219 | echo: 220 | echo Failed to install Taurus SDK. Check if you have required rights. 221 | echo Rerun script with administrator rights if you are installing in a sensitive directory. 222 | exit /b 1 223 | 224 | :usage 225 | echo Usage: ^[-tb ^| --target-board ^] ^[-ts ^| --target-soc^] 226 | echo ^[-tt ^| --target-triplet^] ^[-tp ^| --toolchain-path^] 227 | echo ^[-ip ^| --install-path^] ^[-vp ^| --vegadude-path^] 228 | echo ^[-h ^| --help^] 229 | echo: 230 | echo Option Summary: 231 | echo -tb ^| --target-board Required if --target-soc not provided. 232 | echo Set the target development board to 233 | echo build Taurus for. Adds extra optimisations 234 | echo for board if available. 235 | echo Valid targets are: 236 | echo %s 237 | echo: 238 | echo -ts ^| --target-soc Required if --target-board not provided. 239 | echo Set the target System-on-Chip to build 240 | echo Taurus for. 241 | echo Valid targets are: 242 | echo %s 243 | echo: 244 | echo -tt ^| --target-triplet Required. RISC-V GNU Compiler Target 245 | echo triplet. 246 | echo Example: 'riscv64-unknown-elf' 247 | echo: 248 | echo -tp ^| --toolchain-path Optional. Specify the absolute path of 249 | echo toolchain if it is not present in PATH. 250 | echo: 251 | echo -ip ^| --install-path Optional. Path where Taurus will be 252 | echo installed. 253 | echo: 254 | echo -vp ^| --vegadude-path Optional. Provide vegadude path for taurus integration. 255 | echo Not required if vegadude is already present in PATH. 256 | echo: 257 | echo -h --help Print this message. 258 | echo: 259 | exit /b 0 260 | 261 | :set_target_board 262 | set "TAURUS_TARGET_BOARD=%~2" 263 | goto :parse_args_tail 264 | 265 | :set_target_soc 266 | set "TAURUS_TARGET_SOC=%~2" 267 | goto :parse_args_tail 268 | 269 | :set_target_triplet 270 | set "TAURUS_TARGET_TRIPLET=%~2" 271 | goto :parse_args_tail 272 | 273 | :set_toolchain_path 274 | set "TAURUS_TOOLCHAIN_PATH=%~2" 275 | set "TAURUS_TOOLCHAIN_PATH=%TAURUS_TOOLCHAIN_PATH:\=/%" 276 | goto :parse_args_tail 277 | 278 | :set_install_path 279 | set "TAURUS_INSTALL_PATH=%~2" 280 | set "TAURUS_INSTALL_PATH=%TAURUS_INSTALL_PATH:\=/%" 281 | goto :parse_args_tail 282 | 283 | :set_vegadude_path 284 | set "TAURUS_VEGADUDE_PATH=%~2" 285 | set "TAURUS_VEGADUDE_PATH=%TAURUS_VEGADUDE_PATH:\=/%" 286 | goto :parse_args_tail 287 | -------------------------------------------------------------------------------- /drivers/uart.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file uart.c 3 | @brief Contains routines for UART interface 4 | @detail Includes software functions to initialize, 5 | configure, transmit and receive over UART 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /** 13 | @fn void uart_init(UC uart_number) 14 | @brief default baud rate and frame initialization 15 | @details To initialize UART: Baud Rate = 115200 Clock 25MHz 16 | Calculate Divisor(Divisor = Input frequency / (Baud rate X 16) ) 17 | for the baud rate and configure uart register. UART frame is initialized by 18 | setting the data bits,parity bits and stop bits 19 | 8 Data bits, 1 Stop bit, no Parity, 20 | Disable DR interrupt & THRE interrupt 21 | @param[in] unsigned char(uart_number) 22 | @param[Out] No ouput parameter. 23 | @return Void function. 24 | */ 25 | void uart_init(UC uart_number) { 26 | UartReg(uart_number).UART_LCR = 0x83; 27 | UartReg(uart_number).UART_DR = 0x0e; //LSB 28 | UartReg(uart_number).UART_IE = 0x00; //MSB 29 | UartReg(uart_number).UART_LCR = 0x03; 30 | UartReg(uart_number).UART_IE = 0x00; 31 | } 32 | 33 | 34 | /** 35 | @fn void uart_set_baud_rate(UC uart_number,UL Baud_rate, UL Uart_clock) 36 | @brief set baud rate for uart 37 | @details Calculate Divisor(Divisor = Input frequency / (Baud rate X 16) ) 38 | for the baud rate and configure uart register. UART frame is initialized by 39 | setting the data bits,parity bits and stop bits 40 | 8 Data bits, 1 Stop bit, no Parity, 41 | Disable DR interrupt & THRE interrupt 42 | @param[in] unsigned char(uart_number) 43 | @param[in] unsigned long(Baud_rate) 44 | @param[in] unsigned long(Uart_clock) 45 | @param[Out] No ouput parameter. 46 | @return Void function. 47 | */ 48 | void uart_set_baud_rate(UC uart_number,UL Baud_rate, UL Uart_clock){ 49 | UL divisor; 50 | divisor = (Uart_clock / (Baud_rate * 16)); 51 | UartReg(uart_number).UART_LCR = 0x83; 52 | UartReg(uart_number).UART_DR = divisor & 0xFF; //LSB 53 | UartReg(uart_number).UART_IE = (divisor >> 0x08) & 0xFF; //MSB(right shift) 54 | UartReg(uart_number).UART_LCR = 0x03; 55 | UartReg(uart_number).UART_IE = 0x00; 56 | } 57 | 58 | 59 | /** 60 | @fn void uart_configure(UC uart_number, UL Baud_rate, UL frame_value, UL Uart_clock) 61 | @brief Baud rate and Frame initialization 62 | @details Calculate Divisor(Divisor = Input frequency / (Baud rate X 16) ) 63 | for the baud rate and configure uart register. UART frame is initialized by 64 | setting the data bits,parity bits and stop bits 65 | Frame value is set as follows: 66 | Bit 7: Divisor latch access .1 for setting baud rate and 0 for access rxr buffer 67 | Bit 6: Break control bit 68 | Bit 5: Stick Parity bit 69 | Bit 4: Even parity bit 70 | Bit 3: Parity Enable bit 71 | Bit 2: Number of stop bit transmitted 72 | Bit 1:0: Number of data bits 73 | @param[in] unsigned char(uart_number) 74 | @param[in] unsigned long(Baud_rate) 75 | @param[in] unsigned long(frame_value) 76 | @param[in] unsigned long(Uart_clock) 77 | @param[Out] No ouput parameter. 78 | @return Void function. 79 | */ 80 | void uart_configure(UC uart_number, UL Baud_rate, UL frame_value, UL Uart_clock) { 81 | UL divisor; 82 | divisor = (Uart_clock / (Baud_rate * 16)); 83 | UartReg(uart_number).UART_LCR = frame_value; //0x83 84 | UartReg(uart_number).UART_DR = divisor & 0xFF; //LSB 85 | UartReg(uart_number).UART_IE = (divisor >> 0x08) & 0xFF; //MSB(right shift) 86 | UartReg(uart_number).UART_LCR &= 0x7f; //DLAB bit to zero 87 | UartReg(uart_number).UART_IE = 0x01; 88 | UartReg(uart_number).UART_IIR_FCR = 0x00; 89 | __asm__ __volatile__ ("fence"); 90 | } 91 | 92 | 93 | /** 94 | @fn void uart_putchar(UC uart_number, UC bTxCharacter, char *error) 95 | @brief 1 byte character transmission 96 | @details Transmit 1 character through uart.Proceeds only when transmitter is idle 97 | @param[in] unsigned char(uart_number-- which uart to be used) 98 | @param[in] unsigned char(bTxCharacter--character to be transmitted) 99 | @param[Out] unsigned char *error : if parity error -1, if Overrun error -2, if framing error -3 100 | no error 0 101 | @return Void function. 102 | */ 103 | void uart_putchar(UC uart_number, UC bTxCharacter, char *error) { 104 | 105 | while ((UartReg(uart_number).UART_LSR & 0x20) != 0x20 106 | && (UartReg(uart_number).UART_LSR & 0x40) != 0x40) 107 | ; //checks whether transmitter id idle and transmitter holding register is empty , to start transmitting 108 | //printf("ready to txmt \n\r"); 109 | UartReg(uart_number).UART_DR = bTxCharacter; 110 | __asm__ __volatile__ ("fence"); 111 | while ((UartReg(uart_number).UART_LSR & 0x20) != 0x20) 112 | ; 113 | //printf("\n tx complete \n\r"); 114 | if ((UartReg(uart_number).UART_LSR & 0x04) == 0x04) { 115 | //printf("ParityError\n\r"); 116 | *error = UART_PARITY_ERROR; 117 | } else if ((UartReg(uart_number).UART_LSR & 0x02) == 0x02) { 118 | //printf("OverrunError\n\r"); //data in buffer is not read before next character was transfered and in FIFO, exceeds the trigger level 119 | *error = UART_OVERRUN_ERROR; 120 | } else if ((UartReg(uart_number).UART_LSR & 0x08) == 0x08) { 121 | //printf("FrammingError\n\r"); //frame does not match with the settings 122 | *error = UART_FRAMING_ERROR; 123 | } else 124 | *error = UART_NO_ERROR; //no error 125 | } 126 | 127 | 128 | /** 129 | @fn UC uart_getchar(UC uart_number, char *error) 130 | @brief 1 byte character reception 131 | @details Receives 1 character thcrough uart 132 | @param[in] unsigned char(uart_number) 133 | @param[Out] unsigned char *error : if parity error -1, if Overrun error -2, 134 | if framing error -3 ,no error 0 135 | @return unsigned char Rxd_data--data received 136 | */ 137 | UC uart_getchar(UC uart_number, char *error) { 138 | UC Rxd_data; 139 | 140 | while ((UartReg(uart_number).UART_LSR & 0x01) != 0x01) 141 | ; //waiting for data 142 | //printf("ready to receive \n\r"); 143 | Rxd_data = UartReg(uart_number).UART_DR; // 144 | 145 | if ((UartReg(uart_number).UART_LSR & 0x04) == 0x04) { 146 | //printf("ParityError\n\r"); 147 | *error = UART_PARITY_ERROR; 148 | } else if ((UartReg(uart_number).UART_LSR & 0x02) == 0x02) { 149 | //printf("OverrunError\n\r"); //data in buffer is not read before next character was transfered and in FIFO, exceeds the trigger level 150 | *error = UART_OVERRUN_ERROR; 151 | } else if ((UartReg(uart_number).UART_LSR & 0x08) == 0x08) { 152 | //printf("FrammingError\n\r"); //frame does not match with the settings 153 | *error = UART_FRAMING_ERROR; 154 | } else 155 | *error = UART_NO_ERROR; //no error 156 | return Rxd_data; 157 | } 158 | 159 | 160 | /** 161 | @fn UC uart_getchar(UC uart_number, char *error) 162 | @brief 1 byte character reception 163 | @details Receives 1 character thcrough uart 164 | @param[in] unsigned char(uart_number) 165 | @param[Out] unsigned char *error : if parity error -1, if Overrun error -2, 166 | if framing error -3 ,no error 0 167 | @return unsigned char Rxd_data--data received 168 | */ 169 | UC uart_getchar_async(UC uart_number, char *error) { 170 | UC Rxd_data; 171 | clock_t start_time=0, end_time=0; 172 | start_time = get_time(); 173 | end_time = start_time + ((1000000*10)/0.025); 174 | 175 | while ((UartReg(uart_number).UART_LSR & 0x01) != 0x01){//waiting for data 176 | start_time = get_time(); 177 | if(start_time > end_time) 178 | break; 179 | } 180 | 181 | //printf("ready to receive \n\r"); 182 | Rxd_data = UartReg(uart_number).UART_DR; // 183 | 184 | if ((UartReg(uart_number).UART_LSR & 0x04) == 0x04) { 185 | //printf("ParityError\n\r"); 186 | *error = UART_PARITY_ERROR; 187 | } else if ((UartReg(uart_number).UART_LSR & 0x02) == 0x02) { 188 | //printf("OverrunError\n\r"); //data in buffer is not read before next character was transfered and in FIFO, exceeds the trigger level 189 | *error = UART_OVERRUN_ERROR; 190 | } else if ((UartReg(uart_number).UART_LSR & 0x08) == 0x08) { 191 | //printf("FrammingError\n\r"); //frame does not match with the settings 192 | *error = UART_FRAMING_ERROR; 193 | } else 194 | *error = UART_NO_ERROR; //no error 195 | return Rxd_data; 196 | } 197 | 198 | 199 | /** 200 | @fn UC uart_getchar(UC uart_number, char *error) 201 | @brief 1 byte character reception 202 | @details Receives 1 character thcrough uart 203 | @param[in] unsigned char(uart_number) 204 | @param[Out] unsigned char *error : if parity error -1, if Overrun error -2, 205 | if framing error -3 ,no error 0 206 | @return unsigned char Rxd_data--data received 207 | */ 208 | UC uart_getchar_sim_txn_rxn(UC uart_number_tx,UC uart_number_rx, char *error,char txdata) { 209 | UC Rxd_data; 210 | UC Tx_flag = 1; 211 | while ((UartReg(uart_number_rx).UART_LSR & 0x01) != 0x01){//waiting for data 212 | if(Tx_flag==1){ 213 | UartReg(uart_number_tx).UART_DR = txdata; 214 | Tx_flag=0; 215 | } 216 | 217 | } 218 | 219 | //printf("ready to receive \n\r"); 220 | Rxd_data = UartReg(uart_number_rx).UART_DR; // 221 | 222 | if ((UartReg(uart_number_rx).UART_LSR & 0x04) == 0x04) { 223 | printf("ParityError\n\r"); 224 | *error = UART_PARITY_ERROR; 225 | } else if ((UartReg(uart_number_rx).UART_LSR & 0x02) == 0x02) { 226 | printf("OverrunError\n\r"); //data in buffer is not read before next character was transfered and in FIFO, exceeds the trigger level 227 | *error = UART_OVERRUN_ERROR; 228 | } else if ((UartReg(uart_number_rx).UART_LSR & 0x08) == 0x08) { 229 | printf("FrammingError\n\r"); //frame does not match with the settings 230 | *error = UART_FRAMING_ERROR; 231 | } else 232 | *error = UART_NO_ERROR; //no error 233 | return Rxd_data; 234 | } 235 | 236 | 237 | /** 238 | @fn void uart_intr_enable(UC uart_number, UC tx_intr, UC rx_intr) 239 | @brief enable uart interrupts 240 | @details enable the uart tx and rx interrupt 241 | @param[in] unsigned char(uart_number) 242 | @param[in] unsigned char(tx_intr) 243 | @param[in] unsigned char(rx_intr) 244 | @param[Out] No ouput parameter. 245 | @return Void function. 246 | */ 247 | void uart_intr_enable(UC uart_number, UC tx_intr, UC rx_intr) { 248 | 249 | //UartReg(uart_number).UART_IE = ((rx_intr << 2) | (tx_intr << 1)); 250 | UartReg(uart_number).UART_IE = ((tx_intr << 1) | (rx_intr)); 251 | __asm__ __volatile__ ("fence"); 252 | } 253 | 254 | 255 | /** @fn uart_intr_handler 256 | * @brief Interrupt handler. 257 | * @details Reads uart controllers status register to distinguish which type of interrupt has occurred. 258 | * @warning 259 | * @param[in] unsigned char 260 | * @param[Out] Returns 1 if Tx intr occurs, 2 if Rx intr occurs. 261 | */ 262 | /*int uart_intr_handler(UC uart_number) { 263 | UC status = 0; 264 | 265 | status = UartReg(uart_number).UART_IIR_FCR; 266 | if((status & 0x02)==0x02) // uart TX intr occurred. 267 | return 1; 268 | else if((status & 0x04)==0x04) 269 | return 2; // uart RX intr occurred. 270 | }*/ 271 | 272 | -------------------------------------------------------------------------------- /drivers/pwmc.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project : MDP 3 | * Name of the file : pwmc.c 4 | * Brief Description of file : Driver for PWM controller. 5 | * Name of Author : Sreeju G R 6 | * Email ID : sreeju@cdac.in 7 | 8 | Copyright (C) 2020 CDAC(T). All rights reserved. 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | ***************************************************************************/ 24 | /** 25 | @file pwmc.c 26 | @brief Contains routines for different PWM options 27 | @detail 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | PWMcntrlRegType gPWMCtransfer; 36 | 37 | 38 | /** @fn void PWMC_Set_Period(UC channel_no, UI period) 39 | * @brief PWM cycle duration. 40 | * @details 41 | 42 | * @param[in] unsigned char channel_no: The channel number to which device is connected (It can be from 0 to 7), 43 | unsigned int period: Minimum value supported is 2. Maximum value supported 2^32 – 1. 44 | * @param[Out] No output parameter 45 | */ 46 | 47 | 48 | void PWMC_Set_Period(UC channel_no, UI period) 49 | { 50 | PWMCreg(channel_no).Period = period; 51 | __asm__ __volatile__ ("fence"); 52 | return; 53 | } 54 | 55 | 56 | /** @fn void PWMC_Set_OnOffTime(UC channel_no, UI time) 57 | * @brief Defined as pulse duration in a PWM cycle 58 | * @details When Alignment register is set for left alignment this register 59 | represents on time or high time of the PWM signal. 60 | 61 | When Alignment register is set for right alignment this register 62 | represents off time or low time of the PWM signal. 63 | 64 | * @param[in] unsigned char channel_no: The channel number to which device is connected (It can be from 0 to 7), 65 | unsigned int time: Minimum value supported is 1. Maximum value supported 2^32 – 1. 66 | * @param[Out] No output parameter 67 | */ 68 | 69 | 70 | void PWMC_Set_OnOffTime(UC channel_no, UI time) 71 | { 72 | PWMCreg(channel_no).On_Off = time; 73 | __asm__ __volatile__ ("fence"); 74 | return; 75 | } 76 | 77 | 78 | /** @fn void PWMC_init(UC channel_no,UC mode,UC align,UC intr_en_dis,UC opc, US repeatCount) 79 | * @brief 80 | * @details 81 | 82 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 83 | unsigned char mode- 00 : PWM Idle, 01: One short mode, 10: Continuous mode, 11: Reserved for future use. 84 | unsigned char align- 00: Left alignment, 01: Right alignment. 10,11: Reserved for future use. 85 | unsigned char intr_en_dis- 0 - Disable interrupt, 1 - Enable interrupt. 86 | unsigned char opc- 0: Output level is Low in idle mode,1: Output level is High in idle mode 87 | unsigned short repeatCount- Repeat count for the PWM cycle. 88 | * @param[Out] No output parameter 89 | */ 90 | 91 | void PWMC_init(UC channel_no,UC mode,UC align,UC intr_en_dis,UC opc, US repeatCount) 92 | { 93 | PWMCreg(channel_no).Control.word = 0; 94 | gPWMCtransfer.Bits.Mode = mode; 95 | gPWMCtransfer.Bits.AC = align; 96 | gPWMCtransfer.Bits.IE = intr_en_dis; 97 | gPWMCtransfer.Bits.OPC = opc; 98 | gPWMCtransfer.Bits.RepeatCount = repeatCount; 99 | 100 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 101 | __asm__ __volatile__ ("fence"); 102 | return; 103 | } 104 | 105 | /** @fn void PWMC_Set_mode(UC channel_no,UC mode) 106 | * @brief 107 | * @details 108 | 109 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 110 | unsigned char mode- 00 : PWM Idle, 01: One short mode, 10: Continuous mode, 11: Reserved for future use. 111 | * @param[Out] No output parameter 112 | */ 113 | void PWMC_Set_mode(UC channel_no,UC mode) 114 | { 115 | gPWMCtransfer.Value = PWMCreg(channel_no).Control.word; 116 | gPWMCtransfer.Bits.Mode = mode; 117 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 118 | __asm__ __volatile__ ("fence"); 119 | return; 120 | } 121 | 122 | /** @fn void PWMC_Set_alignment(UC channel_no,UC align) 123 | * @brief 124 | * @details 125 | 126 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 127 | unsigned char align- 00: Left alignment, 01: Right alignment. 10,11: Reserved for future use. 128 | * @param[Out] No output parameter 129 | */ 130 | void PWMC_Set_alignment(UC channel_no,UC align) 131 | { 132 | gPWMCtransfer.Value = PWMCreg(channel_no).Control.word; 133 | gPWMCtransfer.Bits.AC = align; 134 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 135 | __asm__ __volatile__ ("fence"); 136 | return; 137 | } 138 | 139 | /** @fn void PWMC_Set_RepeatCount(UC channel_no,US repeatCount) 140 | * @brief 141 | * @details 142 | 143 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 144 | unsigned short repeatCount- Repeat count for the PWM cycle. 145 | * @param[Out] No output parameter 146 | */ 147 | void PWMC_Set_RepeatCount(UC channel_no,US repeatCount) 148 | { 149 | gPWMCtransfer.Value = PWMCreg(channel_no).Control.word; 150 | gPWMCtransfer.Bits.RepeatCount = repeatCount; 151 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 152 | __asm__ __volatile__ ("fence"); 153 | return; 154 | } 155 | 156 | /** @fn PWMC_Enable 157 | * @brief Enale PWM. 158 | * @details 159 | 160 | * @param[in] No input parameter 161 | * @param[Out] No output parameter 162 | */ 163 | void PWMC_Enable(void) 164 | { 165 | UI *ptrPWM_Global_Ctrl = (UI*)PWMC_GCR_REG; 166 | *ptrPWM_Global_Ctrl = 0; 167 | *ptrPWM_Global_Ctrl = PWM_GPE; 168 | __asm__ __volatile__ ("fence"); 169 | return; 170 | } 171 | 172 | 173 | /** @fn PWMC_Enable_with_intr 174 | * @brief 175 | * @details 176 | 177 | * @param[in] No input parameter 178 | * @param[Out] No output parameter 179 | */ 180 | 181 | void PWMC_Enable_with_intr(void) 182 | { 183 | UI *ptrPWM_Global_Ctrl = (UI*)PWMC_GCR_REG; 184 | *ptrPWM_Global_Ctrl = 0; 185 | *ptrPWM_Global_Ctrl = (PWM_GPE|PWM_GIE); 186 | __asm__ __volatile__ ("fence"); 187 | return; 188 | } 189 | 190 | 191 | 192 | /** @fn void PWMC_Disable(void) 193 | * @brief Disable interrupt 194 | * @details 195 | 196 | * @param[in] No input parameter 197 | * @param[Out] No output parameter 198 | */ 199 | 200 | void PWMC_Disable(void) 201 | { 202 | UI *ptrPWM_Global_Ctrl = (UI*)PWMC_GCR_REG; 203 | *ptrPWM_Global_Ctrl = (0<<0); 204 | __asm__ __volatile__ ("fence"); 205 | return; 206 | } 207 | 208 | 209 | /** @fn void gen_LeftAlign_PWM_OneShort_Mode(UC channel_no,UI on_time,US repeatCount,UI period) 210 | * @brief Generate a One short mode Left aligned PWM signal in the specified channel number. 211 | * @details 212 | 213 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 214 | unsigned int on_time: Minimum value supported is 1. Maximum value supported 2^32 – 1.(represents on time or high time of the PWM signal.) 215 | unsigned short repeatCount- Repeat count for the PWM cycle. 216 | unsigned int period: Minimum value supported is 2. Maximum value supported 2^32 – 1. 217 | * @param[Out] No output parameter 218 | */ 219 | 220 | void gen_LeftAlign_PWM_OneShort_Mode(UC channel_no,UI on_time,US repeatCount,UI period) 221 | { 222 | 223 | PWMCreg(channel_no).On_Off = on_time; 224 | __asm__ __volatile__ ("fence"); 225 | 226 | gPWMCtransfer.Bits.Mode = PWM_ONE_SHORT_MODE; 227 | gPWMCtransfer.Bits.AC = PWM_LEFT_ALIGN; 228 | //gPWMCtransfer.Bits.IE = intr_en_dis; 229 | //gPWMCtransfer.Bits.OPC = opc; 230 | gPWMCtransfer.Bits.RepeatCount = repeatCount; 231 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 232 | __asm__ __volatile__ ("fence"); 233 | 234 | PWMCreg(channel_no).Period = period; 235 | __asm__ __volatile__ ("fence"); 236 | 237 | PWMC_Enable(); 238 | 239 | return; 240 | } 241 | 242 | 243 | /** @fn void gen_RightAlign_PWM_OneShort_Mode(UC channel_no,UI off_time,US repeatCount,UI period) 244 | * @brief Generate a One short mode Right aligned PWM signal in the specified channel number. 245 | * @details 246 | 247 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 248 | unsigned int off_time: Minimum value supported is 1. Maximum value supported 2^32 – 1.(represents off time or low time of the PWM signal.) 249 | unsigned short repeatCount- Repeat count for the PWM cycle. 250 | unsigned int period: Minimum value supported is 2. Maximum value supported 2^32 – 1. 251 | * @param[Out] No output parameter 252 | */ 253 | 254 | void gen_RightAlign_PWM_OneShort_Mode(UC channel_no,UI off_time,US repeatCount,UI period) 255 | { 256 | 257 | PWMCreg(channel_no).On_Off = off_time; 258 | __asm__ __volatile__ ("fence"); 259 | 260 | gPWMCtransfer.Bits.Mode = PWM_ONE_SHORT_MODE; 261 | gPWMCtransfer.Bits.AC = PWM_RIGHT_ALIGN; 262 | //gPWMCtransfer.Bits.IE = intr_en_dis; 263 | //gPWMCtransfer.Bits.OPC = opc; 264 | gPWMCtransfer.Bits.RepeatCount = repeatCount; 265 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 266 | __asm__ __volatile__ ("fence"); 267 | 268 | PWMCreg(channel_no).Period = period; 269 | __asm__ __volatile__ ("fence"); 270 | 271 | PWMC_Enable(); 272 | 273 | return; 274 | } 275 | 276 | 277 | /** @fn void gen_LeftAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period) 278 | * @brief Generate a Continuous mode Left aligned PWM signal in the specified channel number. 279 | * @details 280 | 281 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 282 | unsigned int on_time: Minimum value supported is 1. Maximum value supported 2^32 – 1.(represents on time or high time of the PWM signal.) 283 | unsigned int period: Minimum value supported is 2. Maximum value supported 2^32 – 1. 284 | * @param[Out] No output parameter 285 | */ 286 | 287 | void gen_LeftAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period) 288 | { 289 | 290 | PWMCreg(channel_no).On_Off = on_time; 291 | printf("\rHIGH"); 292 | __asm__ __volatile__ ("fence"); 293 | 294 | gPWMCtransfer.Bits.Mode = PWM_CONTINUOUS_MODE; 295 | gPWMCtransfer.Bits.AC = PWM_LEFT_ALIGN; 296 | //gPWMCtransfer.Bits.IE = intr_en_dis; 297 | //gPWMCtransfer.Bits.OPC = opc; 298 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 299 | __asm__ __volatile__ ("fence"); 300 | 301 | PWMCreg(channel_no).Period = period; 302 | __asm__ __volatile__ ("fence"); 303 | 304 | PWMC_Enable(); 305 | return; 306 | } 307 | 308 | 309 | 310 | /** @fn void gen_RightAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period) 311 | * @brief Generate a Continuous mode Right aligned PWM signal in the specified channel number. 312 | * @details 313 | 314 | * @param[in] unsigned char channel_no- The channel number to which device is connected (It can be from 0 to 7), 315 | unsigned int off_time: Minimum value supported is 1. Maximum value supported 2^32 – 1.(represents off time or low time of the PWM signal.) 316 | unsigned int period: Minimum value supported is 2. Maximum value supported 2^32 – 1. 317 | * @param[Out] No output parameter 318 | */ 319 | 320 | void gen_RightAlign_PWM_Continuous_Mode(UC channel_no,UI on_time,UI period) 321 | { 322 | 323 | PWMCreg(channel_no).On_Off = on_time; 324 | __asm__ __volatile__ ("fence"); 325 | 326 | gPWMCtransfer.Bits.Mode = PWM_CONTINUOUS_MODE; 327 | gPWMCtransfer.Bits.AC = PWM_RIGHT_ALIGN; 328 | //gPWMCtransfer.Bits.IE = intr_en_dis; 329 | //gPWMCtransfer.Bits.OPC = opc; 330 | PWMCreg(channel_no).Control.word = gPWMCtransfer.Value; 331 | __asm__ __volatile__ ("fence"); 332 | 333 | PWMCreg(channel_no).Period = period; 334 | __asm__ __volatile__ ("fence"); 335 | 336 | PWMC_Enable(); 337 | return; 338 | } 339 | 340 | 341 | 342 | 343 | /** @fn void pwmc_register_isr(UC pwmc_ch_number,void (*pwmc_isr)()) 344 | * @brief Register PWMC isr 345 | * @details 346 | 347 | * @param[in] unsigned char pwmc_ch_number: The channel number to which device is connected (It can be from 0 to 7), 348 | function pointer to the pwmc isr(). 349 | * @param[Out] No output parameter 350 | */ 351 | void pwmc_register_isr(UC pwmc_ch_number,void (*pwmc_isr)()) 352 | { 353 | UC irq_no; 354 | #if __riscv_xlen == 64 355 | if(pwmc_ch_number == 0) 356 | irq_no = 54; 357 | else if(pwmc_ch_number == 1) 358 | irq_no = 55; 359 | else if(pwmc_ch_number == 2) 360 | irq_no = 56; 361 | else if(pwmc_ch_number == 3) 362 | irq_no = 57; 363 | else if(pwmc_ch_number == 4) 364 | irq_no = 58; 365 | else if(pwmc_ch_number == 5) 366 | irq_no = 59; 367 | else if(pwmc_ch_number == 6) 368 | irq_no = 60; 369 | else if(pwmc_ch_number == 7) 370 | irq_no = 61; 371 | #else 372 | if(pwmc_ch_number == 0) 373 | irq_no = 24; 374 | else if(pwmc_ch_number == 1) 375 | irq_no = 25; 376 | else if(pwmc_ch_number == 2) 377 | irq_no = 26; 378 | else if(pwmc_ch_number == 3) 379 | irq_no = 27; 380 | else if(pwmc_ch_number == 4) 381 | irq_no = 28; 382 | else if(pwmc_ch_number == 5) 383 | irq_no = 29; 384 | else if(pwmc_ch_number == 6) 385 | irq_no = 30; 386 | else if(pwmc_ch_number == 7) 387 | irq_no = 31; 388 | #endif 389 | interrupt_enable(irq_no); //Enable interrupt in controller. 390 | irq_register_handler(irq_no, pwmc_isr); 391 | } 392 | 393 | UC pwm_idle_check_opc(UC channel_no){ 394 | gPWMCtransfer.Value = PWMCreg(channel_no).Control.word; 395 | if(gPWMCtransfer.Bits.OPC & 0x01 ==0x01) 396 | return 1; 397 | else 398 | return 0; 399 | } 400 | 401 | -------------------------------------------------------------------------------- /drivers/spi.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project : MDP 3 | * Name of the file : spi.c 4 | * Brief Description of file : Driver to control the spi device. 5 | * Name of Author : Sreeju G R 6 | * Email ID : sreeju@cdac.in 7 | 8 | Copyright (C) 2020 CDAC(T). All rights reserved. 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | ***************************************************************************/ 24 | 25 | /** 26 | @file spi.c 27 | @brief Contains routines for different SPI funtions 28 | @detail 29 | */ 30 | 31 | 32 | 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | SPIcntrlRegType gSPItransfer; 40 | 41 | /** @fn void SPI_init(UC spi_number) 42 | @brief Initialize SPI controller. 43 | @details Initialise SPI with the default setting. 44 | @warning 45 | @param[in] unsigned char spi_number: Denotes the selected SPI. 46 | @param[Out] No output parameter 47 | */ 48 | 49 | void SPI_init(UC spi_number) { 50 | 51 | UC rx = 0; 52 | UI reg_data = 0; 53 | 54 | SPIreg(spi_number).Baudrate = (SPI_BAUD_CFD_16<<4); // Baud divisor 55 | 56 | gSPItransfer.Bits.Dbits = 8; // Bits per transfer set to 8. 57 | gSPItransfer.Bits.CSAAT = LOW; // CSAAT signal is low. 58 | 59 | gSPItransfer.Bits.SPIrxTxIntr = RX_TX_INTR_DIS; // Both Rx & Tx interrupts disabled. 60 | 61 | gSPItransfer.Bits.Mode = 3; // Mode set as '3' 62 | gSPItransfer.Bits.DataOrder = MSB; // MSB bit is transferred first. 63 | gSPItransfer.Bits.PeriphType = 0; // Peripheral type is Fixed peripheral. 64 | gSPItransfer.Bits.PeriphChipSelect = 0; // Peripheral chip select is '0'. 65 | 66 | SPIreg(spi_number).Control.hword = gSPItransfer.Value; // Update value to register 67 | __asm__ __volatile__ ("fence"); 68 | return; 69 | } 70 | 71 | /** @fn void SPI_config(UC spi_number, SPIcntrlRegType spi_control_reg) 72 | @brief Customise the SPI controller's initialize setting. 73 | @details Read the details below. 74 | 75 | SPI Control word details 76 | ************************ 77 | [15:13] Reserved R/W “000” 78 | [12:9] DBITS R/W “0000” 79 | 8: CSAAT : ‘0’ Chip Select Active After Transfer When this bit is set, the chip select line remains active low until transfer to another peripheral is required, or this bit is cleared. 80 | 7: SPTIE : SPI Transmit Interrupt Enable. 81 | ‘0’= Interrupt disabled. 82 | ‘1’= Interrupt enabled. 83 | If enabled interrupt generated when data is loaded from SPI_TDR to Transmit Shift Register. 84 | 85 | 86 | 6: SPI Receive Interrupt Enable 87 | ‘0’= Interrupt disabled. 88 | ‘1’= Interrupt enabled. 89 | If enabled interrupt generated when data is loaded from Receive Shift Register to SPI_RDR 90 | 5: CPOL R/W ‘0’ Clock Polarity .See table 1 91 | 4: CPHA R/W ‘0’ Clock Phase. See table 1 92 | 3: LSB/MSB First. This bit selects LSB/MSB first data transfer format. 93 | ‘0’ = MSB first transfer format 94 | ‘1’ = LSB first transfer format 95 | 2: PS R/W ‘0’. 96 | Fixed peripheral-0. 97 | Variable peripheral-1. 98 | 1,0: PCS1, PCS0 R/W ‘0’ Peripheral Chip select. Active only if PS is active. See table 2 99 | 100 | Table 1 101 | ******* 102 | 103 | SPI Clock configuration Modes 104 | ***************************** 105 | ------------------------------------------------- 106 | | SPI-mode | CPOL(bit - 5) | CPHA(bit - 4)| 107 | ------------------------------------------------- 108 | | 0 | 0 | 0 | 109 | | 1 | 0 | 1 | 110 | | 2 | 1 | 0 | 111 | | 3 | 1 | 1 | 112 | ------------------------------------------------- 113 | 114 | 115 | Table 2 116 | ******* 117 | 118 | SPI Clock configuration Modes 119 | ***************************** 120 | --------------------------------------------------------- 121 | | PCS1 (bit - 1) | PCS1 (bit - 0) | CS | 122 | --------------------------------------------------------- 123 | | 0 | 0 | 1110 | 124 | | 0 | 1 | 1101 | 125 | | 1 | 0 | 1011 | 126 | | 1 | 1 | 0111 | 127 | --------------------------------------------------------- 128 | 129 | @warning 130 | @param[in] unsigned char spi_number: Denotes the selected SPI, 131 | unsigned short cword: The control word to be written to SPI control register. 132 | for the selected SPI. 133 | @param[Out] No output parameter 134 | 135 | */ 136 | 137 | void SPI_config(UC spi_number, SPIcntrlRegType spi_control_reg) { 138 | 139 | SPIreg(spi_number).Control.hword = spi_control_reg.Value;// Update value to register 140 | //printf("\n\r version %x", version); 141 | 142 | __asm__ __volatile__ ("fence"); 143 | return; 144 | } 145 | /** @fn void SPI_set_baud(UC spi_number, UC bBaudCFD) 146 | @brief Set the baud frequency divider value to SPI controller baud register. 147 | @details 148 | ------------------------------------------------- 149 | | BAUD | CLk freq Divider | 150 | ------------------------------------------------- 151 | | 0 | 4 | 152 | | 1 | 8 | 153 | | 2 | 16 | 154 | | 3 | 32 | 155 | | 4 | 64 | 156 | | 5 | 128 | 157 | | 6 | 256 | 158 | | 7 | 512 | 159 | | 8 | 1024 | 160 | | 9 | 2048 | 161 | | 10-15 | reserved | 162 | ------------------------------------------------- 163 | @warning 164 | @param[in] unsigned char spi_number: Denotes the selected SPI, 165 | unsigned char bBaudCFD: The baud frequency divisor value. 166 | @param[Out] No output parameter 167 | */ 168 | void SPI_set_baud(UC spi_number, UC bBaudCFD) { 169 | 170 | SPIreg(spi_number).Baudrate = (bBaudCFD << 4); //Set the baud frequency divider value 171 | __asm__ __volatile__ ("fence"); 172 | return; 173 | } 174 | 175 | /** @fn UI SPI_get_slave_select(UC spi_number) 176 | @brief Read the slave select value. 177 | @details Read the slave select value at bit positions 16 and 17. 178 | @warning 179 | @param[in] unsigned char spi_number: Denotes the selected SPI. 180 | @param[Out] slave select value as 32 bit data 181 | */ 182 | UI SPI_get_slave_select(UC spi_number) { 183 | UI read_data = 0; 184 | 185 | read_data = SPIreg(spi_number).RxData; // Read SPI RX data reg value. 186 | read_data = ((read_data & 0x30000) >> 16);// Extract the value at bit positions 16 & 17. 187 | return read_data; 188 | } 189 | 190 | /** @fn void SPI_set_slave_select(UC spi_number, UI slave_sel_val) 191 | @brief Write the slave select value. 192 | @details Write the slave select value at bit positions 16 and 17. 193 | @warning 194 | @param[in] unsigned char spi_number: Denotes the selected SPI. 195 | unsigned int slave_sel_val: The Slave select bits. 196 | @param[Out] No output parameter 197 | */ 198 | void SPI_set_slave_select(UC spi_number, UI slave_sel_val) { 199 | 200 | UI write_data = 0, read_data = 0; 201 | read_data = SPIreg(spi_number).TxData; 202 | write_data = read_data | (slave_sel_val << 16); 203 | SPIreg(spi_number).TxData = write_data; 204 | return; 205 | } 206 | 207 | /** @fn UC SPI_check_overrun(UC spi_number) 208 | @brief Checks for overrun 209 | @details Checks if overrun occurred or not by reading SPI controller's status register. 210 | @warning 211 | @param[in] unsigned char spi_number: Denotes the selected SPI. 212 | @param[Out] returns 1 if overrun occurs otherwise 0. 213 | */ 214 | UC SPI_check_overrun(UC spi_number) { 215 | UC status = 0; 216 | 217 | status = SPIreg(spi_number).Status; 218 | if (status & (1 << 5)) 219 | return 1; 220 | else 221 | return 0; 222 | } 223 | 224 | /** @fn void SPI_set_intr(UC spi_number, UC tx_intr, UC rx_intr) 225 | @brief Enable/Disable SPI interrupts. 226 | @details Enable/Disable the SPI Tx and Rx interrupt. 227 | @warning 228 | @param[in] unsigned char spi_number: Denotes the selected SPI, 229 | unsigned char tx_intr: 1 to enable tx intr, 0 to disable tx intr. 230 | unsigned char rx_intr: 1 to enable tx intr, 0 to disable tx intr. 231 | @param[Out] No output parameter 232 | */ 233 | void SPI_set_intr(UC spi_number, UC tx_intr, UC rx_intr) { 234 | UC intr_val = 0; 235 | US cword = 0; 236 | 237 | cword = SPIreg(spi_number).Control.hword; 238 | intr_val = ((tx_intr << 7) | (rx_intr << 6)); 239 | cword &= 0xFF3F; /* clearing intr */ 240 | cword |= intr_val; 241 | SPIreg(spi_number).Control.hword = cword; 242 | __asm__ __volatile__ ("fence"); 243 | return; 244 | } 245 | 246 | /** @fn US SPI_receive(UC spi_number) 247 | @brief Read data. 248 | @details Read data (16 bit) received in Read data register of SPI controller. 249 | @warning 250 | @param[in] unsigned char spi_number: Denotes the selected SPI 251 | @param[Out] read data as 16 bit value. 252 | */ 253 | US SPI_receive(UC spi_number) { 254 | US bRxData; 255 | UC status = 0; 256 | 257 | while (!((SPIreg(spi_number).Status) & SPI_RX_COMPLETE_BIT)) 258 | ; // Waiting for RX complete bit to set. 259 | bRxData = SPIreg(spi_number).RxData; // Read data. 260 | return bRxData; 261 | } 262 | 263 | /** @fn void SPI_transmit(UC spi_number, US bData) 264 | @brief Write data. 265 | @details Writes data (16 bit) to transmit data register of SPI controller. 266 | @warning 267 | @param[in] unsigned char spi_number: Denotes the selected SPI, 268 | unsigned short bData: The data to be written to tx data register. 269 | @param[Out] No output parameter. 270 | */ 271 | void SPI_transmit(UC spi_number, US bData) { 272 | 273 | SPI_wait_if_busy(spi_number);// Checking if SPI controller is busy or not. Waits if busy. 274 | while (!(SPIreg(spi_number).Status & SPI_TX_HOLD_EMPTY_BIT)) 275 | ; // Check Tx Hold empty bit is set or not. If not wait here. 276 | SPIreg(spi_number).TxData = bData; // Write the data (can be a command or actual data to be written to spi device) 277 | __asm__ __volatile__ ("fence"); 278 | 279 | return; 280 | } 281 | 282 | 283 | 284 | 285 | 286 | 287 | /** @fn void SPI_wait_if_busy(UC spi_number) 288 | @brief Checks if SPI controller is busy. 289 | @details Reads SPI controllers status register to check its busy status. Waits here untill it becomes free. 290 | @warning 291 | @param[in] unsigned char spi_number: Denotes the selected SPI 292 | @param[Out] No output parameter. 293 | */ 294 | void SPI_wait_if_busy(UC spi_number) { 295 | 296 | while (SPIreg(spi_number).Status & SPI_BUSY_BIT) 297 | ; // Read SPI controller status register to check if its busy or not. 298 | //printf("\n\r SPI idle"); 299 | return; 300 | } 301 | 302 | /** @fn void SPI_set_CSAAT_pin(UC spi_number, UC status) 303 | @brief Set CSAAT pin high/low. 304 | @details Sets Chip Select Active After Transfer pin high : This pin must be high when the command/data is more than one byte 305 | and pin must be lowered when the command/data is over. 306 | @warning 307 | @param[in] unsigned char spi_number: Denotes the selected SPI, 308 | unsigned char status: 1 - to make CSAAT pin high, 0 - to make CSAAT pin low. 309 | @param[Out] No output parameter. 310 | */ 311 | void SPI_set_CSAAT_pin(UC spi_number, UC status) { 312 | 313 | if (status == 1) 314 | SPIreg(spi_number).Control.hword |= (1 << 8);// Setting CSAAT bit high. 315 | else 316 | SPIreg(spi_number).Control.hword &= ~(1 << 8); // Setting CSAAT bit low. 317 | __asm__ __volatile__ ("fence"); 318 | return; 319 | } 320 | 321 | /** @fn US SPI_read_rx_reg(UC spi_number) 322 | @brief Read data. 323 | @details Read data (16 bit) received in Read data register of SPI controller. 324 | @warning 325 | @param[in] unsigned char spi_number: Denotes the selected SPI. 326 | @param[Out] read data as 16 bit value. 327 | */ 328 | US SPI_read_rx_reg(UC spi_number) { 329 | US bRxData; 330 | bRxData = SPIreg(spi_number).RxData; // Read SPI data reg value. 331 | return bRxData; 332 | } 333 | 334 | /** @fn void SPI_write_tx_reg(UC spi_number, US bData) 335 | @brief Write data. 336 | @details Writes data (16 bit) to transmit data register of SPI controller. 337 | @warning 338 | @param[in] unsigned char spi_number: Denotes the selected SPI, 339 | unsigned short bData: The data to be written to tx data register. 340 | @param[Out] No output parameter. 341 | */ 342 | void SPI_write_tx_reg(UC spi_number, US bData) { 343 | 344 | SPI_wait_if_busy(spi_number);// Checking if SPI controller is busy or not. Waits if busy. 345 | while (!(SPIreg(spi_number).Status & SPI_TX_HOLD_EMPTY_BIT)) 346 | ; // Check Tx Hold empty bit is set or not. If not wait here. 347 | SPIreg(spi_number).TxData = bData; // Write the data (can be a command or actual data to be written to spi device) 348 | __asm__ __volatile__ ("fence"); 349 | return; 350 | } 351 | 352 | /** @fn void spi_register_isr(UC spi_number, void (*spi_isr)()) 353 | @brief 354 | @details 355 | @warning 356 | @param[in] unsigned char spi_number: Denotes the selected SPI, 357 | unsigned short bData: The data to be written to tx data register. 358 | @param[Out] No output parameter. 359 | */ 360 | void spi_register_isr(UC spi_number, void (*spi_isr)()) { 361 | UC irq_no; 362 | #if __riscv_xlen == 64 363 | if(spi_number == 0) 364 | irq_no = 6; 365 | else if(spi_number == 1) 366 | irq_no = 7; 367 | else if(spi_number == 2) 368 | irq_no = 52; 369 | else if(spi_number == 3) 370 | irq_no = 53; 371 | #else 372 | if (spi_number == 0) 373 | irq_no = 3; 374 | else if (spi_number == 1) 375 | irq_no = 4; 376 | else if (spi_number == 2) 377 | irq_no = 23; 378 | #endif 379 | interrupt_enable(irq_no); //Enable interrupt in controller. 380 | irq_register_handler(irq_no, spi_isr); 381 | } 382 | 383 | /** @fn UC spi_intr_status(UC spi_number) 384 | @brief Read SPI interrupt status. 385 | @details Reads SPI controllers status register to distinguish which type of interrupt has occurred. 386 | @warning 387 | @param[in] unsigned char spi_number: Denotes the selected SPI. 388 | @param[Out] Interrupt status. 389 | */ 390 | UC spi_intr_status(UC spi_number) { 391 | UC status = 0; 392 | if (spi_number == 0) 393 | status = SPIreg(0).Status; //Read SPI 0 status register. 394 | if (spi_number == 1) 395 | status = SPIreg(1).Status; //Read SPI 1 status register. 396 | if (spi_number == 2) 397 | status = SPIreg(2).Status; //Read SPI 2 status register. 398 | if (spi_number == 3) 399 | status = SPIreg(3).Status; //Read SPI 3 status register. 400 | 401 | //read intr ststus reg and return SPI_RX_INTR or SPI_TX_INTR(define these as macros) 402 | 403 | if (status & (1 << 2)) // SPI receive complete interrupt occurred. 404 | { 405 | return SPI_RX_INTR; 406 | } else if (status & (1 << 3)) // SPI TX register empty interrupt occurred. 407 | { 408 | return SPI_TX_INTR; 409 | } 410 | } 411 | 412 | -------------------------------------------------------------------------------- /drivers/qspi.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project : MDP 3 | * Name of the file : spi.c 4 | * Brief Description of file : Driver to control the spi device. 5 | * Name of Author : Sreeju G R 6 | * Email ID : sreeju@cdac.in 7 | 8 | Copyright (C) 2020 CDAC(T). All rights reserved. 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | ***************************************************************************/ 24 | 25 | /** 26 | @file qspi.c 27 | @brief Contains routines for different QSPI flash funtions 28 | @warning QSPI driver is only implemented for Thejas64 29 | @detail 30 | */ 31 | 32 | #if __riscv_xlen == 64 //QSPI driver available only for thejas64 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | CSR_CONFG_TYPE gCSRConfg; 39 | DCR_CONFG_TYPE gDCRConfg; 40 | 41 | /** 42 | @fn void qspi_initialise(UC qspi_number) 43 | @brief Initialises QSPI 44 | @details sets prescalar ,choose mode , chip select high time and flash memory size 45 | Enable QSPI 46 | @param[in] unsigned char (qspi_number) 47 | @param[Out] No ouput parameter. 48 | @return Void function. 49 | 50 | */ 51 | 52 | void qspi_initialise(UC qspi_number) { 53 | 54 | while (1) { //checks whether busy 55 | 56 | if (qspi_wait_if_busy(qspi_number)) 57 | continue; 58 | else 59 | break; 60 | } 61 | 62 | gCSRConfg.Field.CSR_Prescalar = PRESCALAR_MAX; // Sclk/2=00 63 | gCSRConfg.Field.CSR_LSB = 0x01; //QSPI enabled 64 | QSPIReg(qspi_number).QSPI_CSR = gCSRConfg.value; 65 | 66 | __asm__ __volatile__ ("fence"); 67 | 68 | while (1) { //checks whether busy 69 | 70 | if (qspi_wait_if_busy(qspi_number)) 71 | continue; 72 | else 73 | break; 74 | } 75 | 76 | gDCRConfg.Field.DCR_ModeCHST = (CHIP_HIGH_TIME << 01) | CK_MODE_0; //Mode 0,Chip select high time =5 cycles 77 | gDCRConfg.Field.DCR_FSize = FLASH_MEMORY_SIZE; //64MB flash memory can be connected 78 | QSPIReg(qspi_number).QSPI_DCR = gDCRConfg.value; 79 | 80 | __asm__ __volatile__ ("fence"); 81 | 82 | } 83 | /** 84 | @fn void qspi_init_transfer(UC qspi_number, UI Clk_Prescalar, UC fifo_thres, UC Auto_poll_stop, UC Poll_Match) 85 | @brief Configuring Configuration registers of qspi 86 | @details Set QSPI Controller parameters in Control portion (lower 32 bits of CSR) 87 | Prescaler: Frequency of operation 88 | chip 0 selected and disabled all interrupts 89 | QSPI enabled and fifo threshold set 90 | Set APMS(Auto_poll_stop) and PMM(Poll_Match) 91 | @param[in] unsigned char (qspi_number) 92 | @param[in] unsigned int (Clk_Prescalar) 93 | @param[in] unsigned char (fifo_thres) 94 | @param[in] unsigned char (Auto_poll_stop) 95 | @param[in] unsigned char (Poll_Match) 96 | @param[Out] No ouput parameter. 97 | @return Void function. 98 | */ 99 | 100 | void qspi_init_transfer(UC qspi_number, UI Clk_Prescalar, UC fifo_thres, 101 | UC Auto_poll_stop, UC Poll_Match) { 102 | 103 | while (1) { //checks whether busy 104 | 105 | if (qspi_wait_if_busy(qspi_number)) 106 | continue; 107 | else 108 | break; 109 | } 110 | gCSRConfg.Field.CSR_Prescalar = Clk_Prescalar; // Sclk/2=00 111 | gCSRConfg.Field.CSR_CsIE = (Poll_Match << 7) | (Auto_poll_stop << 6) | 0x00; //CS0 112 | gCSRConfg.Field.CSR_LSB = (fifo_thres << 2) | (0x01); //QSPI enabled 113 | 114 | QSPIReg(qspi_number).QSPI_CSR = gCSRConfg.value; 115 | 116 | __asm__ __volatile__ ("fence"); 117 | 118 | } 119 | /** 120 | @fn void qspi_read_flash_register(UC qspi_number, UL address, UI dataLength, UC command, UC instr_line, UC data_line, UC *read_data) 121 | @brief reads flash register 122 | @details sets address,data length and data size ,choose required data,instruction line 123 | @param[in] unsigned char (qspi_number) 124 | @param[in] unsigned long (address) 125 | @param[in] unsigned int (dataLength) 126 | @param[in] unsigned char (command) 127 | @param[in] unsigned char (instr_line) 128 | @param[in] unsigned char (data_line) 129 | @param[Out] unsigned char 130 | @return Void function. 131 | 132 | */ 133 | 134 | void qspi_read_flash_register(UC qspi_number, UL address, UI dataLength, 135 | UC command, UC instr_line, UC data_line, UC *read_data) { 136 | 137 | QSPIReg(qspi_number).QSPI_ADLR = ((address << 32) | dataLength); 138 | QSPIReg(qspi_number).QSPI_DSR = 0x00; //8 bit data size 139 | while (1) { //checks whether busy 140 | 141 | if (qspi_wait_if_busy(qspi_number)) 142 | continue; 143 | else 144 | break; 145 | } 146 | QSPIReg(qspi_number).QSPI_CCR = ((INDIRECT_RD << 25) | (data_line << 23) 147 | | (instr_line << 8) | command); 148 | while (1) { //checks for read transfer complete 149 | 150 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 151 | if ((gCSRConfg.Field.CSR_Flag & 0x04) == 0x04) 152 | break; 153 | else 154 | continue; 155 | } 156 | 157 | for (int i = 0; i < dataLength; i++) { 158 | *read_data = QSPIReg(qspi_number).QSPI_DR; 159 | 160 | read_data++; 161 | } 162 | QSPIReg(qspi_number).QSPI_FCR = 0x4F; //cleared all flags except busy 163 | QSPIReg(qspi_number).QSPI_ADLR = 0x00; 164 | __asm__ __volatile__ ("fence"); 165 | } 166 | 167 | /** 168 | @fn void qspi_instrTxt(UC qspi_number, UC instr_line, UC command) 169 | @brief writes flash command to QSPI register 170 | @details writes flash command to QSPI register with the required instruction line 171 | @param[in] unsigned char (qspi_number) 172 | @param[in] unsigned char (instr_line) 173 | @param[in] unsigned char (command) 174 | @param[Out] No ouput parameter. 175 | @return Void function. 176 | 177 | */ 178 | void qspi_instrTxt(UC qspi_number, UC instr_line, UC command) { 179 | 180 | while (1) { //checks whether busy 181 | 182 | if (qspi_wait_if_busy(qspi_number)) 183 | continue; 184 | else 185 | break; 186 | } 187 | 188 | QSPIReg(qspi_number).QSPI_CCR = ((instr_line << 8) | command); 189 | 190 | while (1) { //checks for write transfer complete 191 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 192 | 193 | if ((gCSRConfg.Field.CSR_Flag & 0x08) == 0x08) { 194 | QSPIReg(qspi_number).QSPI_FCR = 0x4F;//cleared all flags except busy 195 | 196 | __asm__ __volatile__ ("fence"); 197 | break; 198 | } else 199 | continue; 200 | 201 | } 202 | } 203 | 204 | /** 205 | @fn void qspi_write_flash_register(UC qspi_number, UL address, UI dataLength, UC command, UC instr_line, UC data_line, UC wr_data) 206 | @brief writes flash register 207 | @details writes flash register with the required instruction line/data line 208 | @param[in] unsigned char (qspi_number) 209 | @param[in] unsigned long (address) 210 | @param[in] unsigned int (dataLength) 211 | @param[in] unsigned char (command) 212 | @param[in] unsigned char (instr_line) 213 | @param[in] unsigned char (data_line) 214 | @param[in] unsigned char (wr_data) 215 | @param[Out] No ouput parameter. 216 | @return Void function. 217 | 218 | */ 219 | 220 | void qspi_write_flash_register(UC qspi_number, UL address, UI dataLength, 221 | UC command, UC instr_line, UC data_line, UC wr_data) { 222 | 223 | QSPIReg(qspi_number).QSPI_ADLR = ((address << 32) | dataLength); 224 | QSPIReg(qspi_number).QSPI_DSR = 0x00; //8 bit data size 225 | QSPIReg(qspi_number).QSPI_DR = wr_data; 226 | QSPIReg(qspi_number).QSPI_CCR = ((data_line << 25) | (INDIRECT_WR << 23) 227 | | (instr_line << 8) | command); 228 | 229 | while (1) { //checks for write transfer complete 230 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 231 | if ((gCSRConfg.Field.CSR_Flag & 0x08) == 0x08) { 232 | QSPIReg(qspi_number).QSPI_FCR = 0x4F;//cleared all flags except busy 233 | __asm__ __volatile__ ("fence"); 234 | break; 235 | } 236 | 237 | else 238 | continue; 239 | } 240 | 241 | } 242 | /** 243 | @fn void qspi_mem_erase(UC qspi_number, UL Address, UI DataLength, UC command, UC instr_line, UC address_line, UC address_size) 244 | @brief erase flash memory 245 | @details erase flash memory with the required instruction line/data line 246 | @param[in] unsigned char (qspi_number) 247 | @param[in] unsigned long (address) 248 | @param[in] unsigned int (dataLength) 249 | @param[in] unsigned char (command) 250 | @param[in] unsigned char (instr_line) 251 | @param[in] unsigned char (address_line) 252 | @param[in] unsigned char (address_size) 253 | @param[Out] nil 254 | @return Void function. 255 | 256 | */ 257 | 258 | void qspi_mem_erase(UC qspi_number, UL Address, UI DataLength, UC command, 259 | UC instr_line, UC address_line, UC address_size) { 260 | 261 | QSPIReg(qspi_number).QSPI_ADLR = ((Address << 32) | DataLength); 262 | QSPIReg(qspi_number).QSPI_CCR = ((INDIRECT_WR << 25) | (address_size << 12) 263 | | (address_line << 10) | (instr_line << 8) | command); 264 | 265 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 266 | if ((gCSRConfg.Field.CSR_Flag & 0x02) == 0x02) { 267 | printf(" Write address out of range \n\r"); 268 | QSPIReg(qspi_number).QSPI_FCR = 0x02;//cleared Write transfer error flag 269 | __asm__ __volatile__ ("fence"); 270 | while (1) 271 | ; 272 | //qspi_failure(); 273 | 274 | } 275 | while (1) { //checks for write transfer complete 276 | 277 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 278 | if ((gCSRConfg.Field.CSR_Flag & 0x08) == 0x08) { 279 | QSPIReg(qspi_number).QSPI_FCR = 0x4F;//cleared all flags except busy 280 | __asm__ __volatile__ ("fence"); 281 | break; 282 | } 283 | 284 | else 285 | continue; 286 | } 287 | 288 | } 289 | 290 | /** 291 | @fn qspi_mem_write(UC qspi_number, UL Address, UI DataLength, UC command, UC instr_line, UC data_line, UC data_size, UC address_line, 292 | UC address_size, UC fifo_threshold, UC *write_data) 293 | @brief write flash memory 294 | @details write flash memory with the required instruction line/data line 295 | @param[in] unsigned char (qspi_number) 296 | @param[in] unsigned long (address) 297 | @param[in] unsigned int (dataLength) 298 | @param[in] unsigned char (command) 299 | @param[in] unsigned char (instr_line) 300 | @param[in] unsigned char (data_line) 301 | @param[in] unsigned char (data_size) 302 | @param[in] unsigned char (address_line) 303 | @param[in] unsigned char (address_size) 304 | @param[in] unsigned char (fifo_threshold) 305 | @param[in] unsigned char (write_data) 306 | @param[Out] No ouput parameter. 307 | @return Void function. 308 | 309 | */ 310 | 311 | void qspi_mem_write(UC qspi_number, UL Address, UI DataLength, UC command, 312 | UC instr_line, UC data_line, UC data_size, UC address_line, 313 | UC address_size, UC fifo_threshold, UC *write_data) { 314 | 315 | UC loop_count_DataReg; 316 | 317 | switch (data_size) { 318 | 319 | case 0x00: 320 | loop_count_DataReg = fifo_threshold / 1; 321 | break; 322 | 323 | case 0x01: 324 | loop_count_DataReg = fifo_threshold / 2; 325 | break; 326 | 327 | case 0x02: 328 | loop_count_DataReg = fifo_threshold / 4; 329 | break; 330 | 331 | case 0x03: 332 | loop_count_DataReg = fifo_threshold / 8; 333 | break; 334 | 335 | } 336 | 337 | QSPIReg(qspi_number).QSPI_ADLR = ((Address << 32) | DataLength); 338 | QSPIReg(qspi_number).QSPI_CCR = ((INDIRECT_WR << 25) | (data_line << 23) 339 | | (address_size << 12) | (address_line << 10) | (instr_line << 8) 340 | | command); 341 | 342 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 343 | if ((gCSRConfg.Field.CSR_Flag & 0x02) == 0x02) { 344 | printf(" Write address out of range \n\r"); 345 | QSPIReg(qspi_number).QSPI_FCR = 0x02;//cleared Write transfer error flag 346 | __asm__ __volatile__ ("fence"); 347 | while (1) 348 | ; 349 | //qspi_failure(); 350 | 351 | } 352 | 353 | for (int j = 0; j < (DataLength / fifo_threshold); j++) { 354 | 355 | while (1) { //wait for free space in fifo 356 | 357 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 358 | if ((gCSRConfg.Field.CSR_Flag & 0x20) == 0x20) { 359 | 360 | break; //break if Txfifo is empty or Fifo have the space for n+1 bytes(63+1) to write 361 | } 362 | } 363 | 364 | QSPIReg(qspi_number).QSPI_DSR = data_size; 365 | 366 | __asm__ __volatile__ ("fence"); 367 | 368 | for (int i = 0; i < loop_count_DataReg; i++) { 369 | 370 | QSPIReg(qspi_number).QSPI_DR = *write_data; 371 | write_data++; 372 | } 373 | 374 | } 375 | 376 | __asm__ __volatile__ ("fence"); 377 | 378 | while (1) { //checks for write transfer complete 379 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 380 | if ((gCSRConfg.Field.CSR_Flag & 0x08) == 0x08) { 381 | QSPIReg(qspi_number).QSPI_FCR = 0x4F;//cleared all flags except busy 382 | __asm__ __volatile__ ("fence"); 383 | break; 384 | } 385 | 386 | else 387 | continue; 388 | } 389 | } 390 | 391 | /** 392 | @fn qspi_mem_read(UC qspi_number, UL Address, UI DataLength, UC command, 393 | UC instr_line, UC data_line, UC data_size, UC address_line, 394 | UC address_size, UC fifo_threshold, UC *read_data) 395 | @brief reads flash memory 396 | @details reads flash memory with the required instruction line/data line 397 | @param[in] unsigned char (qspi_number) 398 | @param[in] unsigned long (address) 399 | @param[in] unsigned int (dataLength) 400 | @param[in] unsigned char (command) 401 | @param[in] unsigned char (instr_line) 402 | @param[in] unsigned char (data_line) 403 | @param[in] unsigned char (data_size) 404 | @param[in] unsigned char (address_line) 405 | @param[in] unsigned char (address_size) 406 | @param[in] unsigned char (fifo_threshold) 407 | @param[in] unsigned char (write_data) 408 | @param[Out] unsigned char 409 | @return Void function. 410 | 411 | */ 412 | 413 | void qspi_mem_read(UC qspi_number, UL Address, UI DataLength, UC command, 414 | UC instr_line, UC data_line, UC data_size, UC address_line, 415 | UC address_size, UC fifo_threshold, UC *read_data) { 416 | 417 | UC loop_count_DataReg; 418 | switch (data_size) { 419 | 420 | case 0x00: 421 | loop_count_DataReg = fifo_threshold / 1; 422 | break; 423 | 424 | case 0x01: 425 | loop_count_DataReg = fifo_threshold / 2; 426 | break; 427 | 428 | case 0x02: 429 | loop_count_DataReg = fifo_threshold / 4; 430 | break; 431 | 432 | case 0x03: 433 | loop_count_DataReg = fifo_threshold / 8; 434 | break; 435 | 436 | } 437 | 438 | QSPIReg(qspi_number).QSPI_ADLR = ((Address << 32) | DataLength); 439 | QSPIReg(qspi_number).QSPI_CCR = ((INDIRECT_RD << 25) | (data_line << 23) 440 | | (address_size << 12) | (address_line << 10) | (instr_line << 8) 441 | | command); 442 | //Qspi_Set_CCR(0x00, 0x0180, 0x3F, 0x12); //Flash Page programming 4QPP, IMode=3 ADMode=3 AdSize=3 AbMode=0 AbSize=0 DCYC=0 DMode=3 FMode=0 AB=00 443 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 444 | 445 | if ((gCSRConfg.Field.CSR_Flag & 0x01) == 0x01) { 446 | printf(" Read address out of range \n\r"); 447 | QSPIReg(qspi_number).QSPI_FCR = 0x01;//cleared Write transfer error flag 448 | __asm__ __volatile__ ("fence"); 449 | while (1) 450 | ; 451 | 452 | } 453 | for (int j = 0; j < (DataLength / fifo_threshold); j++) { 454 | 455 | while (1) { //wait till data available in fifo 456 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 457 | if ((gCSRConfg.Field.CSR_Flag & 0x10) == 0x10) {// break if RxFifo have Fth +1 data to be read 458 | 459 | break; 460 | } else { 461 | 462 | continue; 463 | } 464 | } 465 | QSPIReg(qspi_number).QSPI_DSR = data_size; 466 | __asm__ __volatile__ ("fence"); 467 | 468 | for (int i = 0; i < loop_count_DataReg; i++) {//check read threshold..8 for 64 bit 469 | 470 | *read_data = QSPIReg(qspi_number).QSPI_DR; 471 | read_data++; 472 | } 473 | 474 | } 475 | 476 | while (1) { //checks for transfer complete 477 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 478 | if ((gCSRConfg.Field.CSR_Flag & 0x04) == 0x04) 479 | break; 480 | else 481 | continue; 482 | } 483 | 484 | } 485 | 486 | /** 487 | @fn UC qspi_wait_if_busy(UC qspi_number) 488 | @brief waits if QSPI is busy 489 | @details 490 | @param[Out] No ouput parameter. 491 | @return returns 1 if busy and 0 if idle. 492 | 493 | **/ 494 | 495 | UC qspi_wait_if_busy(UC qspi_number) { 496 | 497 | //checks whether busy 498 | gCSRConfg.value = QSPIReg(qspi_number).QSPI_CSR; 499 | 500 | if ((gCSRConfg.Field.CSR_Flag & 0x80) == 0x80) { 501 | printf("\n\r busy"); 502 | return 1; 503 | } else { 504 | printf("\n\r idle"); 505 | return 0; 506 | } 507 | 508 | } 509 | #endif 510 | -------------------------------------------------------------------------------- /common/stdlib.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file stdlib.c 3 | @brief Contains routines for standard library functions 4 | @detail 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | //volatile unsigned int loop_count=0; 18 | 19 | #define HAS_FLOAT 1 20 | 21 | #define NUM_COUNTERS 2 22 | static uintptr_t counters[NUM_COUNTERS]; 23 | static char* counter_names[NUM_COUNTERS]; 24 | 25 | 26 | void* memset(void* dest, int byte, size_t len); 27 | void* memcpy(void* dest, const void* src, size_t len); 28 | 29 | size_t strnlen(const char *s, size_t n); 30 | #define read_const_csr(reg) ({ unsigned long __tmp; \ 31 | asm ("csrr %0, " #reg : "=r"(__tmp)); \ 32 | __tmp; }) 33 | 34 | #define static_assert(cond) switch(0) { case 0: case !!(long)(cond): ; } 35 | 36 | /** @fn handle_trap 37 | * @brief Trap handler for programs 38 | * @details 39 | * @warning 40 | */ 41 | 42 | uintptr_t __attribute__((weak)) handle_trap(uintptr_t cause, uintptr_t epc, uintptr_t regs[32]) 43 | { 44 | printf("\n\rTRAP\n\r"); 45 | printf("EPC : %lx\n\r",epc); 46 | printf("Cause : %lx\n\r",cause); 47 | printf("badaddress: %lx\n\r",read_const_csr(mbadaddr)); 48 | for(int i=0;i<32;i++) 49 | printf("reg %d : %lx\n\r",i,regs[i]); 50 | 51 | while(1); 52 | //return 0; 53 | } 54 | 55 | /** @fn 56 | * @brief 57 | * @details 58 | */ 59 | void exit(int code) 60 | { 61 | while(1); 62 | } 63 | 64 | 65 | /** @fn 66 | * @brief 67 | * @details 68 | */ 69 | void abort() 70 | { 71 | printf("\n\rABORT\n\r"); 72 | } 73 | 74 | 75 | /** @fn 76 | * @brief 77 | * @details 78 | */ 79 | void printstr(const char* s) 80 | { 81 | printf("\n\rEXIT\n\r"); 82 | } 83 | 84 | 85 | /** @fn 86 | * @brief 87 | * @details 88 | */ 89 | void __attribute__((weak)) thread_entry(int cid, int nc) 90 | { 91 | // multi-threaded programs override this function. 92 | // for the case of single-threaded programs, only let core 0 proceed. 93 | while (cid != 0); 94 | } 95 | 96 | 97 | /** @fn 98 | * @brief 99 | * @details 100 | */ 101 | int __attribute__((weak)) main(int argc, char** argv) 102 | { 103 | // single-threaded programs override this function. 104 | printstr("Implement main(), foo!\n"); 105 | return -1; 106 | } 107 | 108 | 109 | /** @fn 110 | * @brief 111 | * @details 112 | */ 113 | static void init_tls() 114 | { 115 | register void* thread_pointer asm("tp"); 116 | extern char _tls_data; 117 | extern __thread char _tdata_begin, _tdata_end, _tbss_end; 118 | size_t tdata_size = &_tdata_end - &_tdata_begin; 119 | memcpy(thread_pointer, &_tls_data, tdata_size); 120 | size_t tbss_size = &_tbss_end - &_tdata_end; 121 | memset(thread_pointer + tdata_size, 0, tbss_size); 122 | } 123 | 124 | /** @fn 125 | * @brief 126 | * @details 127 | */ 128 | void _init(int cid, int nc) 129 | { 130 | init_tls(); 131 | 132 | GPIO_init(); 133 | 134 | thread_entry(cid, nc); 135 | 136 | // only single-threaded programs should ever get here. 137 | int ret = main(0, 0); 138 | 139 | exit(0); 140 | } 141 | 142 | 143 | #undef putchar 144 | /** @fn 145 | * @brief 146 | * @details 147 | */ 148 | int putchar(int ch) 149 | { 150 | tx_uart(ch); 151 | 152 | if(ch=='\n') 153 | tx_uart('\r'); 154 | 155 | return 0; 156 | } 157 | 158 | 159 | /** @fn 160 | * @brief 161 | * @details 162 | */ 163 | void printhex(UL x) 164 | { 165 | char str[17]; 166 | int i; 167 | for (i = 0; i < 16; i++) 168 | { 169 | str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); 170 | x >>= 4; 171 | } 172 | str[16] = 0; 173 | 174 | printstr(str); 175 | } 176 | 177 | 178 | /** @fn 179 | * @brief 180 | * @details 181 | */ 182 | static inline void printnum(void (*putch)(int, void**), void **putdat, 183 | unsigned long long num, unsigned base, int width, int padc) 184 | { 185 | unsigned digs[sizeof(num)*CHAR_BIT]; 186 | int pos = 0; 187 | 188 | while (1) 189 | { 190 | digs[pos++] = num % base; 191 | if (num < base) 192 | break; 193 | num /= base; 194 | } 195 | 196 | while (width-- > pos) 197 | putch(padc, putdat); 198 | 199 | while (pos-- > 0) 200 | putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); 201 | } 202 | 203 | 204 | /** @fn 205 | * @brief 206 | * @details 207 | */ 208 | static unsigned long long getuint(va_list *ap, int lflag) 209 | { 210 | if (lflag >= 2) 211 | return va_arg(*ap, unsigned long long); 212 | else if (lflag) 213 | return va_arg(*ap, unsigned long); 214 | else 215 | return va_arg(*ap, unsigned int); 216 | } 217 | 218 | 219 | /** @fn 220 | * @brief 221 | * @details 222 | */ 223 | static long long getint(va_list *ap, int lflag) 224 | { 225 | if (lflag >= 2) 226 | return va_arg(*ap, long long); 227 | else if (lflag) 228 | return va_arg(*ap, long); 229 | else 230 | return va_arg(*ap, int); 231 | } 232 | 233 | 234 | #define ZEROPAD (1<<0) /* Pad with zero */ 235 | #define SIGN (1<<1) /* Unsigned/signed long */ 236 | #define PLUS (1<<2) /* Show plus */ 237 | #define SPACE (1<<3) /* Spacer */ 238 | #define LEFT (1<<4) /* Left justified */ 239 | #define HEX_PREP (1<<5) /* 0x */ 240 | #define UPPERCASE (1<<6) /* 'ABCDEF' */ 241 | 242 | #define is_digit(c) ((c) >= '0' && (c) <= '9') 243 | 244 | static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 245 | static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 246 | //static size_t strnlen(const char *s, size_t count); 247 | 248 | 249 | 250 | /*static size_t strnlen(const char *s, size_t count) 251 | { 252 | const char *sc; 253 | for (sc = s; *sc != '\0' && count--; ++sc); 254 | return sc - s; 255 | }*/ 256 | 257 | static int skip_atoi(const char **s) 258 | { 259 | int i = 0; 260 | while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; 261 | return i; 262 | } 263 | 264 | int atoi(char* str) 265 | { 266 | // Initialize result 267 | int res = 0; 268 | 269 | // Iterate through all characters 270 | // of input string and update result 271 | for (int i = 0; str[i] 272 | != '\0'; 273 | ++i) 274 | res = res * 10 + str[i] - '0'; 275 | 276 | // return result. 277 | return res; 278 | } 279 | 280 | float atof(char* s){ 281 | float rez = 0, fact = 1; 282 | if (*s == '-'){ 283 | s++; 284 | fact = -1; 285 | }; 286 | for (int point_seen = 0; *s; s++){ 287 | if (*s == '.'){ 288 | point_seen = 1; 289 | continue; 290 | }; 291 | int d = *s - '0'; 292 | if (d >= 0 && d <= 9){ 293 | if (point_seen) fact /= 10.0f; 294 | rez = rez * 10.0f + (float)d; 295 | }; 296 | }; 297 | return rez * fact; 298 | }; 299 | 300 | 301 | 302 | /** 303 | @fn int accurate_udelay(unsigned int microsec) 304 | @brief Microsecond accurate delay for ARIES board 305 | @param[in] micro seconds 306 | @return int 307 | */ 308 | // unsigned int loop_count; 309 | volatile unsigned int loop_count; 310 | __attribute__ ((noinline)) 311 | int _usleep(unsigned int microsec) 312 | 313 | { 314 | 315 | loop_count=((SYSTEM_FREQUENCY/3)*microsec); 316 | 317 | 318 | asm volatile("addi sp,sp,-8\n\t" 319 | "sw a0,0(sp)\n\t" 320 | "sw a1,4(sp)\n\t" 321 | "la a0, loop_count\n\t" 322 | "lw a1,(a0)\n\t" 323 | "loop_us: \n\t" 324 | "addi a1,a1,-1\n\t" 325 | "bnez a1,loop_us\n\t" 326 | 327 | "lw a0,0(sp)\n\t" 328 | "lw a1,4(sp)\n\t" 329 | "addi sp,sp,8\n\t"); 330 | } 331 | /** 332 | @fn int udelay(unsigned int count) 333 | @brief Millisecond accurate delay for Thejas32 board 334 | @param[in] int count 335 | @return 0 336 | */ 337 | int udelay(unsigned int count) 338 | { 339 | for(int i=0;i<(count*35);i++); //delay millisecond calculation with board mhz 340 | } 341 | /* 342 | int udelay(unsigned int count) 343 | { 344 | clock_t clock_count,target_count; 345 | 346 | clock_count = rdcycle(); //delay millisecond calculation with board mhz 347 | 348 | target_count = clock_count + (count*35); 349 | 350 | while(clock_count < target_count) 351 | { 352 | clock_count = rdcycle(); 353 | } 354 | 355 | }*/ 356 | 357 | __attribute__ ((noinline)) 358 | void usleep(unsigned long delay){ 359 | 360 | asm volatile("mv a5,%0\n\t" 361 | "li a6,1 \n\t" 362 | "beq a5,a6,final\n\t" 363 | "li a6,3 \n\t" 364 | "bge a5,a6,cycle_loop\n\t" 365 | "loop: addi a5,a5,-1\n\t" 366 | "nop\n\t" 367 | "nop\n\t" 368 | "bnez a5,loop\n\t" 369 | "j final\n\t" 370 | "cycle_loop: li a4,33\n\t" 371 | "mul a4,a5,a4\n\t" 372 | //"csrr a6,mcycle\n\t" 373 | "loop1: addi a4,a4,-1\n\t" 374 | "bnez a4,loop1\n\t" 375 | //"addi a5,a5,-1\n\t" 376 | //"bnez a5,cycle_loop\n\t" 377 | "final:\n\t" 378 | : : "r"(delay) : "a5" ); 379 | } 380 | 381 | clock_t get_time() 382 | { 383 | clock_t clock_count; 384 | 385 | clock_count = read_csr(mcycle); 386 | 387 | return clock_count; 388 | } 389 | 390 | 391 | 392 | static char *number(char *str, long num, int base, int size, int precision, int type) 393 | { 394 | char c, sign, tmp[66]; 395 | char *dig = digits; 396 | int i; 397 | 398 | if (type & UPPERCASE) dig = upper_digits; 399 | if (type & LEFT) type &= ~ZEROPAD; 400 | if (base < 2 || base > 36) return 0; 401 | 402 | c = (type & ZEROPAD) ? '0' : ' '; 403 | sign = 0; 404 | if (type & SIGN) 405 | { 406 | if (num < 0) 407 | { 408 | sign = '-'; 409 | num = -num; 410 | size--; 411 | } 412 | else if (type & PLUS) 413 | { 414 | sign = '+'; 415 | size--; 416 | } 417 | else if (type & SPACE) 418 | { 419 | sign = ' '; 420 | size--; 421 | } 422 | } 423 | 424 | if (type & HEX_PREP) 425 | { 426 | if (base == 16) 427 | size -= 2; 428 | else if (base == 8) 429 | size--; 430 | } 431 | 432 | i = 0; 433 | 434 | if (num == 0) 435 | tmp[i++] = '0'; 436 | else 437 | { 438 | while (num != 0) 439 | { 440 | tmp[i++] = dig[((unsigned long) num) % (unsigned) base]; 441 | num = ((unsigned long) num) / (unsigned) base; 442 | } 443 | } 444 | 445 | if (i > precision) precision = i; 446 | size -= precision; 447 | if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; 448 | if (sign) *str++ = sign; 449 | 450 | if (type & HEX_PREP) 451 | { 452 | if (base == 8) 453 | *str++ = '0'; 454 | else if (base == 16) 455 | { 456 | *str++ = '0'; 457 | *str++ = digits[33]; 458 | } 459 | } 460 | 461 | if (!(type & LEFT)) while (size-- > 0) *str++ = c; 462 | while (i < precision--) *str++ = '0'; 463 | while (i-- > 0) *str++ = tmp[i]; 464 | while (size-- > 0) *str++ = ' '; 465 | 466 | return str; 467 | } 468 | 469 | static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type) 470 | { 471 | char tmp[24]; 472 | char *dig = digits; 473 | int i, len; 474 | 475 | if (type & UPPERCASE) dig = upper_digits; 476 | len = 0; 477 | for (i = 0; i < 6; i++) 478 | { 479 | if (i != 0) tmp[len++] = ':'; 480 | tmp[len++] = dig[addr[i] >> 4]; 481 | tmp[len++] = dig[addr[i] & 0x0F]; 482 | } 483 | 484 | if (!(type & LEFT)) while (len < size--) *str++ = ' '; 485 | for (i = 0; i < len; ++i) *str++ = tmp[i]; 486 | while (len < size--) *str++ = ' '; 487 | 488 | return str; 489 | } 490 | 491 | static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type) 492 | { 493 | char tmp[24]; 494 | int i, n, len; 495 | 496 | len = 0; 497 | for (i = 0; i < 4; i++) 498 | { 499 | if (i != 0) tmp[len++] = '.'; 500 | n = addr[i]; 501 | 502 | if (n == 0) 503 | tmp[len++] = digits[0]; 504 | else 505 | { 506 | if (n >= 100) 507 | { 508 | tmp[len++] = digits[n / 100]; 509 | n = n % 100; 510 | tmp[len++] = digits[n / 10]; 511 | n = n % 10; 512 | } 513 | else if (n >= 10) 514 | { 515 | tmp[len++] = digits[n / 10]; 516 | n = n % 10; 517 | } 518 | 519 | tmp[len++] = digits[n]; 520 | } 521 | } 522 | 523 | if (!(type & LEFT)) while (len < size--) *str++ = ' '; 524 | for (i = 0; i < len; ++i) *str++ = tmp[i]; 525 | while (len < size--) *str++ = ' '; 526 | 527 | return str; 528 | } 529 | 530 | #ifdef HAS_FLOAT 531 | 532 | char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); 533 | char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); 534 | static void ee_bufcpy(char *d, char *s, int count); 535 | 536 | void ee_bufcpy(char *pd, char *ps, int count) { 537 | char *pe=ps+count; 538 | while (ps!=pe) 539 | *pd++=*ps++; 540 | } 541 | 542 | static void parse_float(double value, char *buffer, char fmt, int precision) 543 | { 544 | int decpt, sign, exp, pos; 545 | char *digits = NULL; 546 | char cvtbuf[80]; 547 | int capexp = 0; 548 | int magnitude; 549 | 550 | if (fmt == 'G' || fmt == 'E') 551 | { 552 | capexp = 1; 553 | fmt += 'a' - 'A'; 554 | } 555 | 556 | if (fmt == 'g') 557 | { 558 | digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); 559 | magnitude = decpt - 1; 560 | if (magnitude < -4 || magnitude > precision - 1) 561 | { 562 | fmt = 'e'; 563 | precision -= 1; 564 | } 565 | else 566 | { 567 | fmt = 'f'; 568 | precision -= decpt; 569 | } 570 | } 571 | 572 | if (fmt == 'e') 573 | { 574 | digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); 575 | 576 | if (sign) *buffer++ = '-'; 577 | *buffer++ = *digits; 578 | if (precision > 0) *buffer++ = '.'; 579 | ee_bufcpy(buffer, digits + 1, precision); 580 | buffer += precision; 581 | *buffer++ = capexp ? 'E' : 'e'; 582 | 583 | if (decpt == 0) 584 | { 585 | if (value == 0.0) 586 | exp = 0; 587 | else 588 | exp = -1; 589 | } 590 | else 591 | exp = decpt - 1; 592 | 593 | if (exp < 0) 594 | { 595 | *buffer++ = '-'; 596 | exp = -exp; 597 | } 598 | else 599 | *buffer++ = '+'; 600 | 601 | buffer[2] = (exp % 10) + '0'; 602 | exp = exp / 10; 603 | buffer[1] = (exp % 10) + '0'; 604 | exp = exp / 10; 605 | buffer[0] = (exp % 10) + '0'; 606 | buffer += 3; 607 | } 608 | else if (fmt == 'f') 609 | { 610 | digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); 611 | if (sign) *buffer++ = '-'; 612 | if (*digits) 613 | { 614 | if (decpt <= 0) 615 | { 616 | *buffer++ = '0'; 617 | *buffer++ = '.'; 618 | for (pos = 0; pos < -decpt; pos++) *buffer++ = '0'; 619 | while (*digits) *buffer++ = *digits++; 620 | } 621 | else 622 | { 623 | pos = 0; 624 | while (*digits) 625 | { 626 | if (pos++ == decpt) *buffer++ = '.'; 627 | *buffer++ = *digits++; 628 | } 629 | } 630 | } 631 | else 632 | { 633 | *buffer++ = '0'; 634 | if (precision > 0) 635 | { 636 | *buffer++ = '.'; 637 | for (pos = 0; pos < precision; pos++) *buffer++ = '0'; 638 | } 639 | } 640 | } 641 | 642 | *buffer = '\0'; 643 | } 644 | 645 | static void decimal_point(char *buffer) 646 | { 647 | while (*buffer) 648 | { 649 | if (*buffer == '.') return; 650 | if (*buffer == 'e' || *buffer == 'E') break; 651 | buffer++; 652 | } 653 | 654 | if (*buffer) 655 | { 656 | int n = strnlen(buffer,256); 657 | while (n > 0) 658 | { 659 | buffer[n + 1] = buffer[n]; 660 | n--; 661 | } 662 | 663 | *buffer = '.'; 664 | } 665 | else 666 | { 667 | *buffer++ = '.'; 668 | *buffer = '\0'; 669 | } 670 | } 671 | 672 | static void cropzeros(char *buffer) 673 | { 674 | char *stop; 675 | 676 | while (*buffer && *buffer != '.') buffer++; 677 | if (*buffer++) 678 | { 679 | while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++; 680 | stop = buffer--; 681 | while (*buffer == '0') buffer--; 682 | if (*buffer == '.') buffer--; 683 | while (buffer!=stop) 684 | *++buffer=0; 685 | } 686 | } 687 | /** 688 | @fn static char *flt(char *str, double num, int size, int precision, char fmt, int flags) 689 | @brief Floating point format specifier convertor 690 | @param[in] char *str 691 | @param[in] double num 692 | @param[in] int size 693 | @param[in] int precision 694 | @param[in] char fmt 695 | @param[in] int flags 696 | @return The string pointer 697 | */ 698 | static char *flt(char *str, double num, int size, int precision, char fmt, int flags) 699 | { 700 | char tmp[80]; 701 | char c, sign; 702 | int n, i; 703 | 704 | // Left align means no zero padding 705 | if (flags & LEFT) flags &= ~ZEROPAD; 706 | 707 | // Determine padding and sign char 708 | c = (flags & ZEROPAD) ? '0' : ' '; 709 | sign = 0; 710 | if (flags & SIGN) 711 | { 712 | if (num < 0.0) 713 | { 714 | sign = '-'; 715 | num = -num; 716 | size--; 717 | } 718 | else if (flags & PLUS) 719 | { 720 | sign = '+'; 721 | size--; 722 | } 723 | else if (flags & SPACE) 724 | { 725 | sign = ' '; 726 | size--; 727 | } 728 | } 729 | 730 | // Compute the precision value 731 | if (precision < 0) 732 | precision = 6; // Default precision: 6 733 | 734 | // Convert floating point number to text 735 | parse_float(num, tmp, fmt, precision); 736 | 737 | if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp); 738 | if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp); 739 | 740 | n = strnlen(tmp,256); 741 | 742 | // Output number with alignment and padding 743 | size -= n; 744 | if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; 745 | if (sign) *str++ = sign; 746 | if (!(flags & LEFT)) while (size-- > 0) *str++ = c; 747 | for (i = 0; i < n; i++) *str++ = tmp[i]; 748 | while (size-- > 0) *str++ = ' '; 749 | 750 | return str; 751 | } 752 | 753 | #endif 754 | /** 755 | @fn static int ee_vsprintf(char *buf, const char *fmt, va_list args) 756 | @brief Format parser for printf function 757 | @param[in] const char *fmt 758 | @param[in] char *buf 759 | @param[in] va_list args 760 | @return Number of charactes 761 | */ 762 | static int ee_vsprintf(char *buf, const char *fmt, va_list args) 763 | { 764 | int len; 765 | unsigned long num; 766 | int i, base; 767 | char *str; 768 | char *s; 769 | 770 | int flags; // Flags to number() 771 | 772 | int field_width; // Width of output field 773 | int precision; // Min. # of digits for integers; max number of chars for from string 774 | int qualifier; // 'h', 'l', or 'L' for integer fields 775 | 776 | for (str = buf; *fmt; fmt++) 777 | { 778 | if (*fmt != '%') 779 | { 780 | *str++ = *fmt; 781 | continue; 782 | } 783 | 784 | // Process flags 785 | flags = 0; 786 | repeat: 787 | fmt++; // This also skips first '%' 788 | switch (*fmt) 789 | { 790 | case '-': flags |= LEFT; goto repeat; 791 | case '+': flags |= PLUS; goto repeat; 792 | case ' ': flags |= SPACE; goto repeat; 793 | case '#': flags |= HEX_PREP; goto repeat; 794 | case '0': flags |= ZEROPAD; goto repeat; 795 | } 796 | 797 | // Get field width 798 | field_width = -1; 799 | if (is_digit(*fmt)) 800 | field_width = skip_atoi(&fmt); 801 | else if (*fmt == '*') 802 | { 803 | fmt++; 804 | field_width = va_arg(args, int); 805 | if (field_width < 0) 806 | { 807 | field_width = -field_width; 808 | flags |= LEFT; 809 | } 810 | } 811 | 812 | // Get the precision 813 | precision = -1; 814 | if (*fmt == '.') 815 | { 816 | ++fmt; 817 | if (is_digit(*fmt)) 818 | precision = skip_atoi(&fmt); 819 | else if (*fmt == '*') 820 | { 821 | ++fmt; 822 | precision = va_arg(args, int); 823 | } 824 | if (precision < 0) precision = 0; 825 | } 826 | 827 | // Get the conversion qualifier 828 | qualifier = -1; 829 | if (*fmt == 'l' || *fmt == 'L') 830 | { 831 | qualifier = *fmt; 832 | fmt++; 833 | } 834 | 835 | // Default base 836 | base = 10; 837 | 838 | switch (*fmt) 839 | { 840 | case 'c': 841 | if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; 842 | *str++ = (unsigned char) va_arg(args, int); 843 | while (--field_width > 0) *str++ = ' '; 844 | continue; 845 | 846 | case 's': 847 | s = va_arg(args, char *); 848 | if (!s) s = ""; 849 | len = strnlen(s, precision); 850 | if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; 851 | for (i = 0; i < len; ++i) *str++ = *s++; 852 | while (len < field_width--) *str++ = ' '; 853 | continue; 854 | 855 | case 'p': 856 | if (field_width == -1) 857 | { 858 | field_width = 2 * sizeof(void *); 859 | flags |= ZEROPAD; 860 | } 861 | str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); 862 | continue; 863 | 864 | case 'A': 865 | flags |= UPPERCASE; 866 | 867 | case 'a': 868 | if (qualifier == 'l') 869 | str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); 870 | else 871 | str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); 872 | continue; 873 | 874 | // Integer number formats - set up the flags and "break" 875 | case 'o': 876 | base = 8; 877 | break; 878 | 879 | case 'X': 880 | flags |= UPPERCASE; 881 | 882 | case 'x': 883 | base = 16; 884 | break; 885 | 886 | case 'd': 887 | case 'i': 888 | flags |= SIGN; 889 | 890 | case 'u': 891 | break; 892 | 893 | #ifdef HAS_FLOAT 894 | 895 | case 'f': 896 | str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN); 897 | continue; 898 | 899 | #endif 900 | 901 | default: 902 | if (*fmt != '%') *str++ = '%'; 903 | if (*fmt) 904 | *str++ = *fmt; 905 | else 906 | --fmt; 907 | continue; 908 | } 909 | 910 | if (qualifier == 'l') 911 | num = va_arg(args, unsigned long); 912 | else if (flags & SIGN) 913 | num = va_arg(args, int); 914 | else 915 | num = va_arg(args, unsigned int); 916 | 917 | str = number(str, num, base, field_width, precision, flags); 918 | } 919 | 920 | *str = '\0'; 921 | return str - buf; 922 | } 923 | 924 | #undef puts 925 | int puts(const char *p) 926 | { 927 | int i = 0; 928 | while (*p) 929 | { 930 | if( putchar(*p++) == EOF) //if we got the EOF value from writing the char 931 | { 932 | return EOF; 933 | } 934 | } 935 | if(putchar('\n') == EOF) //this will occur right after we quit due to the null terminated character. 936 | { 937 | return EOF; 938 | } 939 | return 1; //to meet spec. 940 | } 941 | 942 | 943 | /** 944 | @fn int printf(const char *fmt, ...) 945 | @brief To print the string in to a standard console 946 | @param[in] const char *fmt 947 | @return Number of printed charactes 948 | */ 949 | #undef printf 950 | int printf(const char *fmt, ...) 951 | { 952 | char buf[256],*p; 953 | va_list args; 954 | int n=0; 955 | 956 | va_start(args, fmt); 957 | ee_vsprintf(buf, fmt, args); 958 | va_end(args); 959 | p=buf; 960 | while (*p) { 961 | putchar((int)*p); 962 | n++; 963 | p++; 964 | } 965 | 966 | return n; 967 | } 968 | /** 969 | @fn int sprintf(char * buffer,const char *fmt, ...) 970 | @brief To print the string in to a give buffer 971 | @param[in] const char *fmt 972 | @param[out] char * buffer 973 | @return Number of printed charactes 974 | */ 975 | #undef sprintf 976 | int sprintf(char * buffer,const char *fmt, ...) 977 | { 978 | char *p; 979 | va_list args; 980 | int n=0; 981 | 982 | va_start(args, fmt); 983 | ee_vsprintf(buffer, fmt, args); 984 | va_end(args); 985 | /*p=buffer; 986 | while (*p) { 987 | putchar((int)*p); 988 | n++; 989 | p++; 990 | }*/ 991 | 992 | return n; 993 | } 994 | 995 | void *_sbrk(int incr) { return (void *)-1; } 996 | 997 | 998 | --------------------------------------------------------------------------------